C# 9 introduced us to record
and the associated with
operator. The with
operator helped us to create or clone copies of existing record instances with set of changes specified.
In C# 10, the C# team has taken the concepts a little further. Let us first examine what we could do in C# 9.
public record Person
{
public string FirstName { get; init;}
public string LastName { get; init;}
}
The above is an example of declaration of a record. Of course you could use the primary constructor to make it simpler, but for the sake of this blog post we will stick to the above declaration.
You could now declare an instance of the record as the following.
var johnDoe = new Person
{
FirstName = "John",
LastName = "Doe"
};
You could create a new instance of johnDoe
and modify only the FirstName
using the with
operator. For example,
var janeDoe = johnDoe with { FirstName = "Jane" };
That is quite simple syntax isn’t it. What if we could extend this to other data types ? That is exactly what C# brings on the table.
Let us declare a regular struct
instead of record
now.
public struct Person
{
public string FirstName { get; init;}
public string LastName { get; init;}
}
You could now use the with
operator to modify an instance of structure. This means the following is still valid despite us changing the definition to be a struct
.
var johnDoe = new Person
{
FirstName = "John",
LastName = "Doe"
};
var janeDoe = johnDoe with { FirstName = "Jane" };
And that isn’t complete yet. You could also use this with anonymous types
. For example, consider the following code.
var johnDoe = new
{
FirstName = "John",
LastName = "Doe"
};
var janeDoe = johnDoe with { FirstName = "Jane" };
This is also valid. You could now create/clone a copy of anonymous types, struct or record using the with
operator. This is quite a good move by the C# team as it would have been such a shame if with
was restricted to record
alone.