Why can't I define a default constructor for a

2018-12-31 17:33发布

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.

标签: c# .net struct
10条回答
长期被迫恋爱
2楼-- · 2018-12-31 18:00

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.

查看更多
无色无味的生活
3楼-- · 2018-12-31 18:10

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!

查看更多
零度萤火
4楼-- · 2018-12-31 18:10

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.

查看更多
回忆,回不去的记忆
5楼-- · 2018-12-31 18:15

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;
查看更多
君临天下
6楼-- · 2018-12-31 18:15
public struct Rational 
{
    private long numerator;
    private long denominator;

    public Rational(long num = 0, long denom = 1)   // This is allowed!!!
    {
        numerator   = num;
        denominator = denom;
    }
}
查看更多
不流泪的眼
7楼-- · 2018-12-31 18:17

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.

查看更多
登录 后发表回答