[c#] Why can't I define a default constructor for a struct in .NET?

In .NET, a value type (C# struct) can't have a constructor with no parameters. According to this post this is mandated by the CLI specification. What happens is that for every value-type a default constructor is created (by the compiler?) which initialized all members to zero (or null).

Why is it disallowed to define such a default constructor?

One trivial use is for rational numbers:

public struct Rational {
    private long numerator;
    private long denominator;

    public Rational(long num, long denom)
    { /* Todo: Find GCD etc. */ }

    public Rational(long num)
    {
        numerator = num;
        denominator = 1;
    }

    public Rational() // This is not allowed
    {
        numerator = 0;
        denominator = 1;
    }
}

Using current version of C#, a default Rational is 0/0 which is not so cool.

PS: Will default parameters help solve this for C# 4.0 or will the CLR-defined default constructor be called?


Jon Skeet answered:

To use your example, what would you want to happen when someone did:

 Rational[] fractions = new Rational[1000];

Should it run through your constructor 1000 times?

Sure it should, that's why I wrote the default constructor in the first place. The CLR should use the default zeroing constructor when no explicit default constructor is defined; that way you only pay for what you use. Then if I want a container of 1000 non-default Rationals (and want to optimize away the 1000 constructions) I will use a List<Rational> rather than an array.

This reason, in my mind, is not strong enough to prevent definition of a default constructor.

This question is related to c# .net struct

The answer is


Just special-case it. If you see a numerator of 0 and a denominator of 0, pretend like it has the values you really want.


Just special-case it. If you see a numerator of 0 and a denominator of 0, pretend like it has the values you really want.


A struct is a value type and a value type must have a default value as soon as it is declared.

MyClass m;
MyStruct m2;

If you declare two fields as above without instantiating either, then break the debugger, m will be null but m2 will not. Given this, a parameterless constructor would make no sense, in fact all any constructor on a struct does is assign values, the thing itself already exists just by declaring it. Indeed m2 could quite happily be used in the above example and have its methods called, if any, and its fields and properties manipulated!


public struct Rational 
{
    private long numerator;
    private long denominator;

    public Rational(long num = 0, long denom = 1)   // This is allowed!!!
    {
        numerator   = num;
        denominator = denom;
    }
}

You can't define a default constructor because you are using C#.

Structs can have default constructors in .NET, though I don't know of any specific language that supports it.


I haven't seen equivalent to late solution I'm going to give, so here it is.

use offsets to move values from default 0 into any value you like. here properties must be used instead of directly accessing fields. (maybe with possible c#7 feature you better define property scoped fields so they remain protected from being directly accessed in code.)

This solution works for simple structs with only value types (no ref type or nullable struct).

public struct Tempo
{
    const double DefaultBpm = 120;
    private double _bpm; // this field must not be modified other than with its property.

    public double BeatsPerMinute
    {
        get => _bpm + DefaultBpm;
        set => _bpm = value - DefaultBpm;
    }
}

This is different than this answer, this approach is not especial casing but its using offset which will work for all ranges.

example with enums as field.

public struct Difficaulty
{
    Easy,
    Medium,
    Hard
}

public struct Level
{
    const Difficaulty DefaultLevel = Difficaulty.Medium;
    private Difficaulty _level; // this field must not be modified other than with its property.

    public Difficaulty Difficaulty
    {
        get => _level + DefaultLevel;
        set => _level = value - DefaultLevel;
    }
}

As I said this trick may not work in all cases, even if struct has only value fields, only you know that if it works in your case or not. just examine. but you get the general idea.


A struct is a value type and a value type must have a default value as soon as it is declared.

MyClass m;
MyStruct m2;

If you declare two fields as above without instantiating either, then break the debugger, m will be null but m2 will not. Given this, a parameterless constructor would make no sense, in fact all any constructor on a struct does is assign values, the thing itself already exists just by declaring it. Indeed m2 could quite happily be used in the above example and have its methods called, if any, and its fields and properties manipulated!


A struct is a value type and a value type must have a default value as soon as it is declared.

MyClass m;
MyStruct m2;

If you declare two fields as above without instantiating either, then break the debugger, m will be null but m2 will not. Given this, a parameterless constructor would make no sense, in fact all any constructor on a struct does is assign values, the thing itself already exists just by declaring it. Indeed m2 could quite happily be used in the above example and have its methods called, if any, and its fields and properties manipulated!


What I use is the null-coalescing operator (??) combined with a backing field like this:

public struct SomeStruct {
  private SomeRefType m_MyRefVariableBackingField;

  public SomeRefType MyRefVariable {
    get { return m_MyRefVariableBackingField ?? (m_MyRefVariableBackingField = new SomeRefType()); }
  }
}

Hope this helps ;)

Note: the null coalescing assignment is currently a feature proposal for C# 8.0.


public struct Rational 
{
    private long numerator;
    private long denominator;

    public Rational(long num = 0, long denom = 1)   // This is allowed!!!
    {
        numerator   = num;
        denominator = denom;
    }
}

You can't define a default constructor because you are using C#.

Structs can have default constructors in .NET, though I don't know of any specific language that supports it.


Shorter explanation:

In C++, struct and class were just two sides of the same coin. The only real difference is that one was public by default and the other was private.

In .NET, there is a much greater difference between a struct and a class. The main thing is that struct provides value-type semantics, while class provides reference-type semantics. When you start thinking about the implications of this change, other changes start to make more sense as well, including the constructor behavior you describe.


You can't define a default constructor because you are using C#.

Structs can have default constructors in .NET, though I don't know of any specific language that supports it.


Here's my solution to the no default constructor dilemma. I know this is a late solution, but I think it's worth noting this is a solution.

public struct Point2D {
    public static Point2D NULL = new Point2D(-1,-1);
    private int[] Data;

    public int X {
        get {
            return this.Data[ 0 ];
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 0 ] = value;
            }
        }
    }

    public int Z {
        get {
            return this.Data[ 1 ];
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 1 ] = value;
            }
        }
    }

    public Point2D( int x , int z ) {
        this.Data = new int[ 2 ] { x , z };
    }

    public static Point2D operator +( Point2D A , Point2D B ) {
        return new Point2D( A.X + B.X , A.Z + B.Z );
    }

    public static Point2D operator -( Point2D A , Point2D B ) {
        return new Point2D( A.X - B.X , A.Z - B.Z );
    }

    public static Point2D operator *( Point2D A , int B ) {
        return new Point2D( B * A.X , B * A.Z );
    }

    public static Point2D operator *( int A , Point2D B ) {
        return new Point2D( A * B.Z , A * B.Z );
    }

    public override string ToString() {
        return string.Format( "({0},{1})" , this.X , this.Z );
    }
}

ignoring the fact I have a static struct called null, (Note: This is for all positive quadrant only), using get;set; in C#, you can have a try/catch/finally, for dealing with the errors where a particular data type is not initialized by the default constructor Point2D(). I guess this is elusive as a solution to some people on this answer. Thats mostly why i'm adding mine. Using the getter and setter functionality in C# will allow you to bypass this default constructor non-sense and put a try catch around what you dont have initialized. For me this works fine, for someone else you might want to add some if statements. So, In the case where you would want a Numerator/Denominator setup, this code might help. I'd just like to reiterate that this solution does not look nice, probably works even worse from an efficiency standpoint, but, for someone coming from an older version of C#, using array data types gives you this functionality. If you just want something that works, try this:

public struct Rational {
    private long[] Data;

    public long Numerator {
        get {
            try {
                return this.Data[ 0 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 0 ];
            }
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 0 ] = value;
            }
        }
    }

    public long Denominator {
        get {
            try {
                return this.Data[ 1 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 1 ];
            }
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 1 ] = value;
            }
        }
    }

    public Rational( long num , long denom ) {
        this.Data = new long[ 2 ] { num , denom };
        /* Todo: Find GCD etc. */
    }

    public Rational( long num ) {
        this.Data = new long[ 2 ] { num , 1 };
        this.Numerator = num;
        this.Denominator = 1;
    }
}

I haven't seen equivalent to late solution I'm going to give, so here it is.

use offsets to move values from default 0 into any value you like. here properties must be used instead of directly accessing fields. (maybe with possible c#7 feature you better define property scoped fields so they remain protected from being directly accessed in code.)

This solution works for simple structs with only value types (no ref type or nullable struct).

public struct Tempo
{
    const double DefaultBpm = 120;
    private double _bpm; // this field must not be modified other than with its property.

    public double BeatsPerMinute
    {
        get => _bpm + DefaultBpm;
        set => _bpm = value - DefaultBpm;
    }
}

This is different than this answer, this approach is not especial casing but its using offset which will work for all ranges.

example with enums as field.

public struct Difficaulty
{
    Easy,
    Medium,
    Hard
}

public struct Level
{
    const Difficaulty DefaultLevel = Difficaulty.Medium;
    private Difficaulty _level; // this field must not be modified other than with its property.

    public Difficaulty Difficaulty
    {
        get => _level + DefaultLevel;
        set => _level = value - DefaultLevel;
    }
}

As I said this trick may not work in all cases, even if struct has only value fields, only you know that if it works in your case or not. just examine. but you get the general idea.


A struct is a value type and a value type must have a default value as soon as it is declared.

MyClass m;
MyStruct m2;

If you declare two fields as above without instantiating either, then break the debugger, m will be null but m2 will not. Given this, a parameterless constructor would make no sense, in fact all any constructor on a struct does is assign values, the thing itself already exists just by declaring it. Indeed m2 could quite happily be used in the above example and have its methods called, if any, and its fields and properties manipulated!


Shorter explanation:

In C++, struct and class were just two sides of the same coin. The only real difference is that one was public by default and the other was private.

In .NET, there is a much greater difference between a struct and a class. The main thing is that struct provides value-type semantics, while class provides reference-type semantics. When you start thinking about the implications of this change, other changes start to make more sense as well, including the constructor behavior you describe.


You can make a static property that initializes and returns a default "rational" number:

public static Rational One => new Rational(0, 1); 

And use it like:

var rat = Rational.One;

Here's my solution to the no default constructor dilemma. I know this is a late solution, but I think it's worth noting this is a solution.

public struct Point2D {
    public static Point2D NULL = new Point2D(-1,-1);
    private int[] Data;

    public int X {
        get {
            return this.Data[ 0 ];
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 0 ] = value;
            }
        }
    }

    public int Z {
        get {
            return this.Data[ 1 ];
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new int[ 2 ];
            } finally {
                this.Data[ 1 ] = value;
            }
        }
    }

    public Point2D( int x , int z ) {
        this.Data = new int[ 2 ] { x , z };
    }

    public static Point2D operator +( Point2D A , Point2D B ) {
        return new Point2D( A.X + B.X , A.Z + B.Z );
    }

    public static Point2D operator -( Point2D A , Point2D B ) {
        return new Point2D( A.X - B.X , A.Z - B.Z );
    }

    public static Point2D operator *( Point2D A , int B ) {
        return new Point2D( B * A.X , B * A.Z );
    }

    public static Point2D operator *( int A , Point2D B ) {
        return new Point2D( A * B.Z , A * B.Z );
    }

    public override string ToString() {
        return string.Format( "({0},{1})" , this.X , this.Z );
    }
}

ignoring the fact I have a static struct called null, (Note: This is for all positive quadrant only), using get;set; in C#, you can have a try/catch/finally, for dealing with the errors where a particular data type is not initialized by the default constructor Point2D(). I guess this is elusive as a solution to some people on this answer. Thats mostly why i'm adding mine. Using the getter and setter functionality in C# will allow you to bypass this default constructor non-sense and put a try catch around what you dont have initialized. For me this works fine, for someone else you might want to add some if statements. So, In the case where you would want a Numerator/Denominator setup, this code might help. I'd just like to reiterate that this solution does not look nice, probably works even worse from an efficiency standpoint, but, for someone coming from an older version of C#, using array data types gives you this functionality. If you just want something that works, try this:

public struct Rational {
    private long[] Data;

    public long Numerator {
        get {
            try {
                return this.Data[ 0 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 0 ];
            }
        }
        set {
            try {
                this.Data[ 0 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 0 ] = value;
            }
        }
    }

    public long Denominator {
        get {
            try {
                return this.Data[ 1 ];
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                return this.Data[ 1 ];
            }
        }
        set {
            try {
                this.Data[ 1 ] = value;
            } catch( Exception ) {
                this.Data = new long[ 2 ] { 0 , 1 };
                this.Data[ 1 ] = value;
            }
        }
    }

    public Rational( long num , long denom ) {
        this.Data = new long[ 2 ] { num , denom };
        /* Todo: Find GCD etc. */
    }

    public Rational( long num ) {
        this.Data = new long[ 2 ] { num , 1 };
        this.Numerator = num;
        this.Denominator = 1;
    }
}

You can make a static property that initializes and returns a default "rational" number:

public static Rational One => new Rational(0, 1); 

And use it like:

var rat = Rational.One;

What I use is the null-coalescing operator (??) combined with a backing field like this:

public struct SomeStruct {
  private SomeRefType m_MyRefVariableBackingField;

  public SomeRefType MyRefVariable {
    get { return m_MyRefVariableBackingField ?? (m_MyRefVariableBackingField = new SomeRefType()); }
  }
}

Hope this helps ;)

Note: the null coalescing assignment is currently a feature proposal for C# 8.0.


You can make a static property that initializes and returns a default "rational" number:

public static Rational One => new Rational(0, 1); 

And use it like:

var rat = Rational.One;

Shorter explanation:

In C++, struct and class were just two sides of the same coin. The only real difference is that one was public by default and the other was private.

In .NET, there is a much greater difference between a struct and a class. The main thing is that struct provides value-type semantics, while class provides reference-type semantics. When you start thinking about the implications of this change, other changes start to make more sense as well, including the constructor behavior you describe.


Just special-case it. If you see a numerator of 0 and a denominator of 0, pretend like it has the values you really want.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to struct

How to search for an element in a golang slice "error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to check for an empty struct? error: expected primary-expression before ')' token (C) Init array of structs in Go How to print struct variables in console? Why Choose Struct Over Class? How to return a struct from a function in C++? Initializing array of structures