C# 为什么类需要默认构造函数,而结构不需要?

C# 为什么类需要默认构造函数,而结构不需要?,c#,class,struct,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(); } 为什么st

查看以下代码

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
不需要默认构造函数,而as
class
需要相同的构造函数?

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

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

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

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

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

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

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

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

当首次创建类类型的存储位置(变量、字段、数组插槽等)时,它将保持
null
。首次创建结构类型的存储位置时,它会保存该类型的一个实例,其中每个字节都已设置为零。不同于C++,.NET没有提供任何类型的方法来在创建该类型的存储位置时执行任何发言,也不应该在它们发生时发生什么。 如果
Foo
是一种类类型,并且code创建了一个数组
bar=new Foo[100]
,那么该数组将创建100个插槽,其中不包含对
Foo
的引用(它们最初为
null
)。要使任何数组槽包含对Foo的引用的代码必须以某种方式获得一个引用,而对Foo的任何引用存在的唯一方式是有人要求类创建一个引用(通过调用其构造函数)

相反,如果
Moo
是一种结构类型,创建一个数组
boz=new Moo[100]
,则该数组将创建100个插槽,每个插槽都是一个
Moo
实例。虽然
Foo
可以保存一个不引用
Foo
实例的值(
null
),但是除了
Moo
实例之外,任何数组插槽都不能保存任何内容。由于创建
Moo
数组本身就创建了
Moo
的实例,而类型在这件事上没有发言权,因此实际上没有任何机制可以让结构类型断言对实例创建的控制权。

当类类型的存储位置(变量、字段、数组插槽等)首次创建时,它保持
null
。首次创建结构类型的存储位置时,它会保存该类型的一个实例,其中每个字节都已设置为零。不同于C++,.NET没有提供任何类型的方法来在创建该类型的存储位置时执行任何发言,也不应该在它们发生时发生什么。 如果
Foo
是一种类类型,并且code创建了一个数组
bar=new Foo[100]
,那么该数组将创建100个插槽,其中不包含对
Foo
的引用(它们最初为
null
)。要使任何数组槽包含对Foo的引用的代码必须以某种方式获得一个引用,而对Foo的任何引用存在的唯一方式是有人要求类创建一个引用(通过调用其构造函数)

相反,如果
Moo
是一种结构类型,创建一个数组
boz=new Moo[100]
,则该数组将创建100个插槽,每个插槽都是一个
Moo
实例。虽然
Foo
可以保存一个不引用
Foo
实例的值(
null
),但任何数组插槽都不能保存任何内容