Skip to content

The init Keyword for Immutable Properties in C#

With C# 9 we got the new init keyword. You may have heard of it when it was introduced, but probably not used it much at the time. Then as with so many new things in the C# language, the new syntax did not offer new functionality but syntactic sugar to get the same results faster. Why should we care now? Because in combination with other newer features in C# that init keyword is a great help.

What was the init keyword again?

The init keyword defines an accessor method in a property or indexer. An init-only setter assigns a value to the property or the indexer element only during object construction. An init enforces immutability, so that once the object is initialized, it can't be changed. – from learn.microsoft.com

The old way with readonly fields

When we wanted to create immutable objects with values that we only could set at the object creation but not afterwards, we would use fields and set the readonly keyword on them:

public class Person
{
    public readonly string FirstName;
    public readonly string LastName;

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

That worked well and if we tried to change the fields, we would end up with this compiler error:

CS0191 A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)

The new way with the init keyword

If we do not have logic that needs to go into the constructor, we can get the same immutable behaviour with a lot less code. All we need to do is to create a property and use init where we used set in the past:

1
2
3
4
5
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

If we try to change a value after we created our object, we get a similar compiler error:

CS8852 Init-only property or indexer 'UserQuery.Person.LastName' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.

Next

With the init keyword we can save a lot of typing to get our immutable objects. We no longer need a constructor and still can make sure that the values cannot be changed. The only downside of this new approach over the one with the constructor is that we cannot enforce that all properties are set. For that we can use the required keyword that we cover in the next post.