为什么我不能为 .NET 中的结构定义默认构造函数? [英] Why can't I define a default constructor for a struct in .NET?

查看:30
本文介绍了为什么我不能为 .NET 中的结构定义默认构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 .NET 中,值类型 (C# struct) 不能有没有参数的构造函数.根据这篇文章,这是 CLI 规范规定的.发生的情况是,对于每个值类型,都会创建一个默认构造函数(由编译器?),它将所有成员初始化为零(或 null).

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

使用当前版本的 C#,默认的 Rational 是 0/0 这不是那么酷.

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

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?

乔恩·斯基特 回答:

以您的示例为例,当有人这样做时,您希望发生什么:

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 应使用 default zeroing 构造函数;这样你只需为你使用的东西付费.然后,如果我想要一个包含 1000 个非默认 Rational 的容器(并且想要优化掉 1000 个结构),我将使用 List 而不是数组.

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# 6 之前很长时间写的,它计划引入在结构中声明无参数构造函数 - 但它们仍然不会在所有情况下被调用(例如创建数组)(最后这个特性 未添加到 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 编写它可以.当您在 C# 中编写new Guid()"时,它会发出与调用普通构造函数不同的 IL.有关这方面的更多信息,请参阅this SO question.

(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.

这篇关于为什么我不能为 .NET 中的结构定义默认构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆