为什么我不能定义默认的构造函数在.NET中的结构?函数、定义、结构、NET

2023-09-02 20:41:55 作者:北京小痞子i

在.NET中,值类型(C#结构)不能有不带参数的构造函数。根据这个帖子这是由CLI规范规定。什么happes是,对于每一个价值型的默认构造函数创建(编译器?),它初始化所有成员为零(或)。

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 happes 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;
    }
}

使用C#的当前版本,默认的理性是 0/0 这是不是很爽。

PS :将默认参数有助于解决这一对C#  4.0或将CLR定义的默认构造函数被调用

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

Jon飞碟双向回答:

要使用你的榜样,你会希望发生的事情,当有人做的:

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

 Rational[] fractions = new Rational[1000];

     

如果它通过你的构造函数运行1000次?

Should it run through your constructor 1000 times?

当然应该,这就是为什么我首先写的默认构造函数。在CLR应该使用的默认的调零的时候没有明确的默认构造函数定义构造函数;这样你只需支付您所使用的。然后,如果我想的容器1000非默认的的Rational S(并希望优化掉了1000的结构),我将使用名单,其中;合理> ,而不是一个数组。

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.

这个原因,在我的脑海里,是没有强大到一个默认的构造函数prevent定义。

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

推荐答案

注意:下面写一个很长一段时间之前,答案C#6,这是计划推出的能力,声明参数构造函数的结构 - 但他们仍然不会被称为在所有情况下(例如,用于创建阵列)(到底这个功能was没有添加到C#6 )。

Note: the answer below was written a long time prior to C# 6, which is planning to introduce the ability to declare parameterless constructors in structs - but they still won't be called in all situations (e.g. for array creation) (in the end this feature was not added to C# 6).

编辑:我已经编辑下面的答案,由于Grauenwolf的洞察CLR

I've edited the answer below due to Grauenwolf's insight into the CLR.

在CLR允许值类型有参数的构造函数,但C#不。我相信这是因为它会引入一个期望的构造函数被调用时,它不会。例如,考虑一下:

The CLR allows value types to have parameterless constructors, but C# doesn't. I believe this is because it would introduce an expectation that the constructor would be called when it wouldn't. For instance, consider this:

MyStruct[] foo = new MyStruct[1000];

的CLR是能够做到这一点很有效地只是通过分配适当的内存和归零这一切了。如果它必须运行MYSTRUCT构造1000倍,这将是一个很大的效率较低。 (事实上​​,它并没有 - 如果你的执行的有参数的构造函数,它不会跑,当你创建一个数组,或者当你有一个未初始化的实例变量)

The CLR is able to do this very efficiently just by allocating the appropriate memory and zeroing it all out. If it had to run the MyStruct constructor 1000 times, that would be a lot less efficient. (In fact, it doesn't - if you do have a parameterless constructor, it doesn't get run when you create an array, or when you have an uninitialized instance variable.)

在C#中的基本规则是对任何类型的默认值,不能依赖于任何初始化。现在,他们的可以的都允许定义参数构造函数,但不是必需的构造函数在所有情况下执行的 - 但这样会导致更多的混乱。 (或者至少,所以我相信按照这种说法。)

The basic rule in C# is "the default value for any type can't rely on any initialization". Now they could have allowed parameterless constructors to be defined, but then not required that constructor to be executed in all cases - but that would have led to more confusion. (Or at least, so I believe the argument goes.)

编辑:用你的榜样,你会希望发生的事情,当有人做的:

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

Rational[] fractions = new Rational[1000];

如果它通过你的构造函数运行1000次?

Should it run through your constructor 1000 times?

如果没有,我们结束了1000无效的有理数 如果确实如此,那么我们可能浪费了工作负荷,如果我们要填补实际值到数组中。

编辑:(回答有点多的问题)的参数的构造函数不是由编译器创建。值类型不必具有构造至于CLR而言 - 尽管事实证明它的可以的,如果你把它写在IL。当你写新的GUID()在C#中发出不同的IL,如果你调用一个正常的构造函数你会得到什么。请参见这太问题关于这方面多一点。

(Answering a bit more of the question) The parameterless constructor isn't created by the compiler. Value types don't have to have constructors as far as the CLR is concerned - although it turns out it can if you write it in IL. When you write "new Guid()" in C# that emits different IL to what you get if you call a normal constructor. See this SO question for a bit more on that aspect.

我的犯罪嫌疑人的,有没有与参数构造函数的框架的任何值类型。毫无疑问,NDepend的能告诉我,如果我问好听足够了...那C#禁止它事实上是一个足够大的提示,我想它可能是一个坏主意。

I suspect that there aren't any value types in the framework with parameterless constructors. No doubt NDepend could tell me if I asked it nicely enough... The fact that C# prohibits it is a big enough hint for me to think it's probably a bad idea.