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

为什么不允许定义这样的默认构造函数?

有理数的一个微不足道的用途是:

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,这并不酷.

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


Jon Skeet人回答:

举个例子,如果有人这样做了,你希望发生什么:

 Rational[] fractions = new Rational[1000];

它应该在构造函数中运行1000次吗?

当然应该,这就是为什么我首先编写默认构造函数的原因.当没有定义显式默认构造函数时,CLR应该使用default zeroing构造函数;这样你只需为你使用的东西付费.如果我想要Rational0个非默认的Rational个容器(并且想要优化掉Rational0个 struct ),我将使用List<Rational>而不是array.

在我看来,这个原因不足以阻止定义默认构造函数.

推荐答案

Note:下面的答案早在C#6之前就已经写好了,C#6计划引入在 struct 中声明无参数构造函数的功能——但它们仍然不会在所有情况下都被调用(例如,对于数组创建)(最后这个特性是was not added to C# 6).


编辑:由于格劳恩沃尔夫对CLR的洞察,我编辑了下面的答案.

CLR允许值类型具有无参数构造函数,但C#没有.我相信这是因为它会引入一种预期,即构造函数将在不调用时被调用.例如,考虑以下内容:

MyStruct[] foo = new MyStruct[1000];

只需分配适当的内存并将其全部清零,CLR就能够非常高效地完成此操作.如果它必须运行MyStruct构造函数do0次,效率就会大大降低.(事实上,它没有-如果您do有一个无参数的构造函数,那么当您创建数组时,或者当您有一个未初始化的实例变量时,它不会运行.)

C#中的基本规则是"任何类型的默认值都不能依赖于任何初始化".现在,他们允许定义无参数构造函数,但不要求在所有情况下都执行该构造函数——但这会导致更多的混乱.(或者至少,我认为这种说法是正确的.)

编辑:以你的例子来说,当有人这样做时,你希望发生什么:

Rational[] fractions = new Rational[1000];

它应该通过您的构造函数运行1000次吗?

  • 如果不是,我们最终会得到1000个无效的理性
  • 如果是这样的话,如果我们打算用实际值填充数组,那么我们可能会浪费大量的工作.

Edit:(回答更多的问题)无参数构造函数不是由编译器创建的.就CLR而言,值类型不一定要有构造函数-尽管如果您用IL编写它,结果会是can.当您用C#编写"new Guid()"时,它会发出与调用普通构造函数时不同的IL.有关这方面的更多信息,请参见this SO question.

Isuspect确认框架中没有任何具有无参数构造函数的值类型.如果我问得够客气的话NDepend肯定会告诉我的.C#禁止它的事实足以让我认为这可能是个坏主意.

.net相关问答推荐

为什么Regex.Escape支持数字符号和空格?

为什么我在环境变量中有不同的值?

如何知道变量是否只是指向另一个对象的pointer或者它是否可以独立存在

如何正确使用await using语法?

MongoDB GridFs with C#,如何存储图片等文件?

无法解析此引用.找不到程序集

使用 Thread.Abort() 有什么问题

如何从标头中检索基本身份验证凭据?

C# 的部分类是糟糕的设计吗?

extern 在 C# 中是如何工作的?

app.config 文件和 XYZ.settings 文件有什么区别?

RNGCryptoServiceProvider 的优缺点

如何以编程方式 Select ListView 中的项目?

实体框架无法加载指定的元数据资源

新的 netstandardapp 和 netcoreapp TFM 有什么区别?

如何在可取消的异步/等待中处理 TransactionScope?

string.Empty vs null.你用哪一个?

List 是否保证项目将按照添加的顺序返回?

通过继承扩展枚举

程序员应该使用 SSIS,如果是,为什么?