Thomas Ardal

Freelance software consultant and entrepreneur building SaaS applications like elmah.io

Primary Constructors in C# 6.0

In my previous post, inspired by the Future of C# talk at GOTO, I looked at Initializers, making it possible to assign a value to an auto-property at declaration, just as with a field. This post is about another piece of syntactic sugar in the up-coming version 6.0 of C#: Primary Constructors.

Continuing the example from before, assigning values to the Movie class through a constructor, could look like this:

public class Movie
{
    public string Title { get; private set; }
 
    public List<string> Genres { get; private set; }
 
    public Movie(string title, List<string> genres)
    {
        Title = title;
        Genres = genres;
    }
}

A constructor assigns values to the two auto properties Title and Genres.

Let’s look at how Primary Constructors in C# 6.0 can be used to optimize the code above:

public class Movie(string title, List<string> genres)
{
    public string Title { get; } = title;
 
    public List<string> Genres { get; } = genres;
}

Once again the constructor is missing and no need to specify a private setter. Notice the parameters added just right of the class definition. This tells the compiler to add a constructor to the Movie class with two parameters: title and genres. We use our knowledge of the previous blog post, to assign the constructor parameters to properties through initializers. Magic.

The decompiled code looks as expected:

public class Movie
{
    private readonly string <Title>k__BackingField
    private readonly List<string> <Genres>k__BackingField;
    
    public string Title
    {
        get { return this.<Title>k__BackingField; }
    }
 
    public List<string> Genres
    {
        get { return this.<Genres>k__BackingField; }
    }
    
    public Movie(string title, List<string> genres)
    {
    	this.<Title>k__BackingField = title;
    	this.<Genres>k__BackingField = genres;
    	base..ctor();
    }
}

A constructor is generated with the same parameters as specified on the primary constructor and values assigned each auto-property. As with initializers, all of the syntactic sugar only exists on compile time, making it possible to execute this bad boy on previous versions of .NET.

Let’s look at a more complex example before we move on. Only one primary constructor per class is allowed. You do have the possibility to specify additional constructors through the usual syntax and you can even use this to invoke your primary constructor as illustrated in the following example:

public class Movie(string title, List<string> genres)
{
    public string Title { get; } = title;
 
    public List<string> Genres { get; } = genres;
 
    public int Runtime { get; private set; }
 
    public Movie(string title, List<string> genres, int runtime) : this(title, genres)
    {
        Runtime = runtime;
    }
}

You probably get it by now but to be explicit and consistent, let’s look at the decompiled code:

public class Movie
{
    private readonly string <Title>k__BackingField
    private readonly List<string> <Genres>k__BackingField;
    private readonly int <Runtime>k__BackingField
    
    public string Title
    {
        get { return this.<Title>k__BackingField; }
    }
    
    public List<string> Genres
    {
        get { return this.<Genres>k__BackingField; }
    }
    
    public int Runtime
    {
        get { return this.<Runtime>k__BackingField; }
        private set { this.<Runtime>k__BackingField = value; }
    }
 
    public Movie(string title, List<string> genres)
    {
        this.<Title>k__BackingField = title;
        this.<Genres>k__BackingField = genres;
        base();
    }
 
    public Movie(string title, List<string> genres, int runtime) : this(title, genres)
    {
        this.Runtime = runtime;
    }
}

In the following post I will check out Declaration Expressions and Static Using.

Show Comments