Ziad Akiki
Ziad Akiki

Reputation: 2680

Kotlin "apply" equivalent in C#

When using Kotlin, one could use apply to set multiple properties of an existing object and keeping the code cleaner, for example instead of:

person.firstName = "John"
person.lastName = "Doe"
person.phone = "123 456 789"

We can use:

person.apply {
   firstName = "John"
   lastName = "Doe"
   phone = "123 456 789"
}

Is there an equivalent to the apply in C#?

The closest to this is the using but it can't be used this way as far as I know.

Edit: I know of object initializer in C#, but I'm actually looking for something that can be done for existing objects (for example an object fetched from the database).

Upvotes: 9

Views: 3908

Answers (6)

Ivan Koshelev
Ivan Koshelev

Reputation: 4270

After copying Apply into several projects, i made a nuget package.

dotnet add package Object.Extensions.ScopeFunction

It offers extension methods Apply, ApplyForEach and Map (which lets you override return).

var permissionsMissingTestContext = new TestContext
{
    Users = GetStandardUsers().ApplyForEach(x => x.Permissions = new Permission[0]),
    SecurityPolicy = GetStandardSecurityPolicy().Apply(x => x.ShowWarningWhenPermissionsMissing = true),
    AnonymousPageUrl = GetStandardConfig().Map(x => new Url(x.PermissionsMissingScreenUrl)),
    Timeout = GetTestTimeout()?.Map(x => TimeSpan.FromSeconds(x)) ?? TimeSpan.FromSeconds(30)
}

Nuget

Upvotes: 1

user2430020
user2430020

Reputation: 91

Try this.... https://dev.to/amay077/kotlins-scope-functions-in-c-pbn

Code pasted below for convenience, but the above link is the source...

static class ObjectExtensions 
{
  // Kotlin: fun <T, R> T.let(block: (T) -> R): R
  public static R Let<T, R>(this T self, Func<T, R> block) 
  {
    return block(self);
  }

  // Kotlin: fun <T> T.also(block: (T) -> Unit): T
  public static T Also<T>(this T self, Action<T> block)
  {
    block(self);
    return self;
  }   
}

Can be used like this....

var model = new MyModel().Also(m => {
  m.Initialize();
  m.Load(path);
});

Upvotes: 9

Nenad
Nenad

Reputation: 26687

There is currently no support in C# (version 8) for grouped multi-property assignment outside of object initialization.

Similar support exists in VB.NET and has been proposed for C# 9.

Little bit of historical context

In Visual Basic.NET there is similar statement - With:

    With person
        .FirstName = "John"
        .LastName = "Doe"
        .Phone = "123 456 789"
    End With

This one was carried from Visual Basic 6 for backward compatibility (previous, non .NET Version of language).

C# team (Anders Heilsberg himself told the story somewhere) argued that With statement decreases code readability and did not want to introduce it in the language. From what I have seen With statements can be nested and can creating quite a confusion of what is going on.

As many others have already mentioned, there is object initializer syntax that is quite similar:

var person = new Person
{
   firstName = "John",
   lastName = "Doe",
   phone = "123 456 789"
};

Future - C# 9

As pointed out in another (deleted) answer, there is an open proposal for records and With expression, to be added in C# 9:

person with { firstName = "John", lastName = "Doe", phone = "123 456 789" };

Bonus Tip

However, most important advice I can give you, to avoid annoying fellow C# developer who might work on your code - we don't use camelCase in C# for public properties and methods, because C# is not Java. We use PascalCase! :)

Upvotes: 4

Joel Coehoorn
Joel Coehoorn

Reputation: 416039

With an object initializer:

var person = new Person
{
   firstName = "John",
   lastName = "Doe",
   phone = "123 456 789"
};

After you already have the object, you can give yourself a short variable:

var p = person;
p.firstName = "Jane";
p.lastName = "Smith";
p.phone = "987 654 321";

//later:
Console.WriteLine(person.lastName); //will output "Smith"

which is less still less code than the apply option.

Upvotes: 2

colinD
colinD

Reputation: 2039

Object initializers allow you to do that but only at instanciation of an object.

Like

var person = new Person
{
   FirstName = "John",
   LastName = "Doe",
   Phone = "123 456 789"
}

Upvotes: 1

Guapo
Guapo

Reputation: 3482

You can use it in this way with object initializers:

var person = new Person
{
   FirstName = "John",
   LastName = "Doe",
   Phone = "123 456 789"
};

Or with a constructor:

var person = new Person("John", "Doe", "123 456 789");

Your class would have to look like this for the constructor option:

class Person
{
    public Person(string firstName, string lastName, string phone)
    {
        FirstName = firstName;
        LastName = lastName;
        Phone = phone;
    }

    public string FirstName { get;set; }
    public string LastName { get;set; }
    public string Phone { get;set; }
}

Upvotes: 4

Related Questions