Making primary constructor parameters read-only

 
 
  • Gérald Barré

C# 12 introduced a new feature called Primary constructor. This feature allows us to define a constructor directly in the class declaration.

C#
// You can define a constructor directly in the class declaration.
public readonly struct Distance(double dx, double dy)
{
    public readonly double Magnitude { get; } = Math.Sqrt(dx * dx + dy * dy);
    public readonly double Direction { get; } = Math.Atan2(dy, dx);
}

This feature is useful to define immutable types. However, the compiler does not enforce the immutability of the parameters. For instance, the following code compiles:

C#
public class Foo(double value)
{
    // Overriding "value" is ok as it's allowed to update a parameter in C#
    // But many people expect the parameter to be read-only like in records
    public void UpdateValue(double newValue) => value = newValue;
}

There are multiple ways to solve this issue and be sure the parameter value is not modified.

#Solution 1: using a read-only field

To make the parameter read-only, you can create a readonly field with the same name as the parameter and assign the value of the parameter to the field. However, this is a lot of boilerplate code:

C#
public class Foo(double value)
{
    // readonly field with the same name as the parameter
    private readonly double value = value;

    // Error CS0191: A readonly field cannot be assigned to
    public void UpdateValue(double newValue) => value = newValue;
}

#Solution 2: using a Roslyn analyzer

Another solution is to use a Roslyn analyzer to report all cases where a parameter is assigned. Meziantou.Analyzer provides a diagnostic to report this issue. You can install the package using the following command:

Shell
dotnet add package Meziantou.Analyzer

Once the package is installed, the rule MA0143 reports all assignments to the primary constructor parameters in your project or usages as ref or out parameters. For instance, the following code will report an error:

#Additional resources

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub