Succinct initialization pattern

Succinct lazy initialization patterns with newer C# features

Home DailyDrop

Daily Knowledge Drop

Sometimes objects need to be initialized lazily - two newer C# features, the null-coalescing assignment operator ??= and the target-typed new expression makes the lazy initialization cleaner and more succinct.


Example

In the examples, we have a Album class which contains an optional list of Song instances:

public class Album
{
    private readonly string _name;

    private readonly List<Song> _songs;

    public Album(string name, List<Song> songs = null)
    {
        _name = name;
        _songs = songs;

        // See examples below on how to 
        // do the _songs initialization
    }
}

public class Song
{
    private readonly string _name;

    public Song(string name)
    {
        _name = name;
    }
}

If no Song list is passed into the constructor, then the _song variable needs to be initialized to an empty list. Doing this will prevent having to have checks throughout the code to determine if the Song list is null or not. There are multiple ways to do this, but this post focuses on the "more traditional" method, and the new "succinct" method.


Traditional lazy init

Traditionally (before any of the newer C# features were introduced), the constructor might look something like this:

public Album(string name, List<Song> songs = null)
{
    _name = name;
    _songs = songs;

    // check if _songs is null
    if(_songs == null)
    {
        // initialize to an empty list
        _songs = new List<Song>();
    }
}

The variable is checked to determine if its null or not, and if it is, then explicitly initialized to an empty list. Nothing inherently wrong with this approach - it just takes four lines of code to lazily initialize a variable.


Succinct lazy init

As mentioned, the two newer C# features allow for this code to be more succinct:

public Album(string name, List<Song> songs = null)
{
    _name = name;
    _songs = songs;

    _songs ??= new();
}
  • The null-coalescing assignment operator ??= assigns the value of the right-hand side to the left-hand side, only if the left-hand side is null
  • The target-typed new expression, new allows for the inferring of the type from the declaration, instead of having to explicitly specify the type in full

Four lines of code have been reduced to one!


Notes

A very minor change, which is not a necessity or requirement when coding - however is does result in cleaner, more succinct code. Over time, it also does reduce coding time by reducing the number of key strokes required by the developer.


References

David Fowler Tweet

Daily Drop 205: 18-11-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net init lazy initialization