查看以下代码
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
需要相同的呢?
答案 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
的实例,而该类型在该问题上没有任何发言权,因此实际上没有一种机制可以通过这种机制来控制实例创建。