Reputation: 2680
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
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)
}
Upvotes: 1
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
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.
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"
};
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" };
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
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
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
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