Skip to content
Carmel Eve By Carmel Eve Software Engineer I
How to fully initialize types in their constructor with C# nullable using the async factory pattern

Here at endjin, we've recently enabled the new nullable references features in all of our projects. This has led me to a realisation that I often don't think as much as I should about object initialisation patterns. A couple of weeks ago I ran into an issue where I was trying to initalise an object, but the initialisation involved asynchronous operations so couldn't be done in a constructor.

When I first created the class I did this:

public class Thing
{
    public string AString { get; private set; }
    
    public static async Task<Thing> CreateThingAsync()
    {
        return new Thing()
        {
            AString = await GetStringAsync()
        };
    }
}
The Introduction to Rx.NET 2nd Edition (2024) Book, by Ian Griffiths & Lee Campbell, is now available to download for FREE.

Where the asynchronous inititialisation is done via a factory method. However, this means that a set function is required for the property, and also, when nullable references are enabled you get this warning:

Warning message saying "Non-nullable property 'AString' is uninitialized. Consider declaring property as nullable.

This is because the AString property is not initialised in the constructor and is therefore technically able to be null. It would be better to be able to make the property truly readonly, and to ensure that it is always initialised as non-null.

Programming C# 12 Book, by Ian Griffiths, published by O'Reilly Media, is now available to buy.

To do this we can use the async factory method pattern:

public class Thing
{
    private Thing(string aString)
    {
        this.AString = aString;
    }

    public string AString { get; }
    
    public static async Task<Thing> CreateThingAsync()
    {
        var aString = await GetStringAsync();
        return new Thing(aString);
    }
}

Here we have a constructor which takes a string, which we use in the initialiser to produce a fully populated object. Also, as the constructor is private we know that the objects can only be initalisated from inside the Thing class. And, as the constructor takes a non-nullable string, we will get a warning if we try and pass anything that could be null in.

For example, if the GetStringAsync method returned a nullable string:

public static async Task<string?> GetStringAsync()
{
    await Task.Delay(1).ConfigureAwait(false);

    return null;
}

Then we would see this warning from the compiler when we try to pass it into the consructor:

Warning message saying "possible null reference assignment"

This is a simple pattern but one that I think is incredibly useful in avoiding partial instantiation and null reference exceptions!

FAQs

How do you ensure a C# non-nullable property is always initialized? Use the factory method pattern as shown here.
How do you create readonly objects in C# with async initialisation? Use the async factory factory method pattern as shown here.

Carmel Eve

Software Engineer I

Carmel Eve

Carmel is a software engineer and LinkedIn Learning instructor. She worked at endjin from 2016 to 2021, focused on delivering cloud-first solutions to a variety of problems. These included highly performant serverless architectures, web applications, reporting and insight pipelines, and data analytics engines. After a three-year career break spent travelling around the world, she rejoined endjin in 2024.

Carmel has written many blog posts covering a huge range of topics, including deconstructing Rx operators, agile estimation and planning and mental well-being and managing remote working.

Carmel has released two courses on LinkedIn Learning - one on the Az-204 exam (developing solutions for Microsoft Azure) and one on Azure Data Lake. She has also spoken at NDC, APISpecs, and SQLBits, covering a range of topics from reactive big-data processing to secure Azure architectures.

She is passionate about diversity and inclusivity in tech. She spent two years as a STEM ambassador in her local community and taking part in a local mentorship scheme. Through this work she hopes to be a part of positive change in the industry.

Carmel won "Apprentice Engineer of the Year" at the Computing Rising Star Awards 2019.