Blog

15. September 2020

Combining nullability and immutability

In my previous blog article we discovered the C# 9 language features init properties and records to deal with the concept of immutability. If you are not familiar with the concepts I’d recommend to read this article before you continue.

With C# 8 the nullable feature was introduced and it was possible to express your intention if a property can be null or not. For further details have a look at https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references.

In this blog article I write about how nullability meats immutability.

Immutability and nullability before C# 9

If you declare an immutable class with a non-nullable field before C# 9 you set all properties via constructor parameters.

public class Person 
{ 
    public string Name { get; } 
    public DateTime Birthdate { get; } 
    
    public Person(string name, DateTime birthdate) 
    { 
        Name = name; 
        Birthdate = birthdate; 
    }
}

When we create an object and pass a null value into the „name“ parameter the IDE complains about the null assignment at the object creation side.

Immutability and nullability with C# 9

As stated in my previous blog article we can make use of init properties and create immutable objects using property initializer.

public record Person 
{ 
    public string Name { get; init; }
    public DateTime Birthdate { get; init; }
    
    public override string ToString()
        => $"{Name} born at {Birthdate:dd.MM.yyyy}";
}

Like in the above example with C# 8 I was also expecting the IDE to complain at the object creation side if I do not set the non-nullable property.

var person = new Person
{
    // no warning altough Name is not set
    Birthdate = DateTime.Now
};

Unfortunately I do not get a warning at the object creation side but at the property declaration.

The drawback is that you might end up with very long constructors the more data your record holds. As you cannot make use of property initializer you might need to introduce a builder pattern which normally can be avoided with property initializer.

However C# 9 is not yet released and there is an ongoing discussion on Github on how to handle these cases.