为什么类需要默认构造函数但不需要结构?

时间:2013-08-29 12:20:04

标签: c# class struct

查看以下代码

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需要相同的呢?

3 个答案:

答案 0 :(得分:3)

始终 struct中的无参数构造函数 - 您无法定义自己的构造函数。它将始终将所有字段初始化为其默认值。这实际上是CLR的要求,尽管CLR本身并未将其称为构造函数,并且在C#规范的第11.3.8节中进行了描述。 (虽然C#不允许你为结构体声明自己的无参数构造函数,但CLR会这样做 - 而且有时会调用。有关更多信息,请参阅my blog post on the topic。)

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

首次创建类类型的存储位置(变量,字段,数组槽等)时,它将保留null。首次创建结构类型的存储位置时,它将保存一个类型的实例,其中每个字节都已设置为零。与C ++不同,.NET没有提供任何类型的方法,可以在何时创建该类型的存储位置,以及在它们存在时应该发生什么。

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

相比之下,如果Foo是结构类型,创建数组Moo,则会创建包含100个插槽的数组,每个插槽 boz = new Moo[100]实例。虽然Moo可以保存一个不引用Foo实例的值(null),但是没有任何数组插槽能够保存{{1}以外的任何内容。实例。由于创建Foo数组本身就会创建Moo的实例,而该类型在该问题上没有任何发言权,因此实际上没有一种机制可以通过这种机制来控制实例创建。