0

查看以下代码

public class ABC
{
    public ABC(int a)
    {
    }
}

public struct XYZ
{
    public XYZ(int a)
    {
    }
}

public class Test
{
    //This is invalid.
    ABC _abc = new ABC();

    //This is valid. Why?
    XYZ _xyz = new XYZ();
}

为什么struct不要求默认构造函数与class要求相同?

4

3 回答 3

3

a中总是有一个无参数的构造函数,struct你不能定义自己的构造函数。它将始终将所有字段初始化为其默认值。这实际上是 CLR 的要求,尽管 CLR 本身并不将其称为构造函数,并且在 C# 规范的第 11.3.8 节中进行了描述。(虽然 C# 不允许您为结构声明自己的无参数构造函数,但 CLR 会 -有时会调用它。有关更多信息,请参阅我的博客文章。)

通过在 a 上调​​用无参数构造函数创建的值struct始终与数组或实例/静态字段中的“未初始化”值相同。

然而,类具有不同的“默认”值,因为引用类型的字段(或数组元素)将是null默认值。在不指定任何值的情况下,无法保证创建类的实例。如果您自己为类指定任何构造函数,C# 编译器将不会提供默认构造函数,如 C# 规范第 10.11.4 节所述。

于 2013-08-29T12:23:42.543 回答
2

因为类的默认构造函数(引用类型)仅在未实现显式构造函数(即它不存在)时才公开。一个结构(值类型)甚至不需要是new'd,可以这么说。您可以使用表示没有它的结构的变量 - 即它不会是null,无论如何(也就是说,它根本不需要存在)。

于 2013-08-29T12:22:07.897 回答
1

当第一次创建类类型的存储位置(变量、字段、数组槽等)时,它保存null. 当第一次创建结构类型的存储位置时,它会保存一个类型的实例,其中每个字节都已设置为零。与 C++ 不同,.NET 没有为一种类型提供任何方法来决定何时可以创建该类型的存储位置,也没有提供任何方法来决定何时创建该类型的存储位置。

如果Foo是类类型并且代码创建了一个数组bar = new Foo[100],则该数组将创建有 100 个不包含对Foo(它们最初是null)的引用的插槽。想要使任何数组槽包含对 a 的引用的代码Foo必须以某种方式获得一个,并且任何引用Foo存在的唯一方法是如果有人要求类创建一个(通过调用其构造函数)。

相比之下,如果Moo是结构体类型,创建一个数组boz = new Moo[100],这个数组会创建100个槽,每个槽都是一个Moo实例。尽管 aFoo可以保存null不引用 的实例的值 ( ),但没有一个Foo数组槽能够保存除Moo实例之外的任何内容。由于创建一个数组Moo固有地创建实例Moo的类型没有任何发言权,因此实际上没有任何机制可以让结构类型断言对实例创建的控制。

于 2013-08-29T20:25:10.503 回答