在不使用new关键字的情况下创建结构时会发生什么?

时间:2018-02-18 12:57:13

标签: c#

在不使用new关键字的情况下制作结构时,幕后会发生什么?

假设我们有这个结构:

struct Person
{
    public int Age;
    public string Name;
}

在Main()方法中,我决定在没有new关键字的情况下创建它的实例:

Person p;

现在,如果我尝试访问p.Age,我将收到一个编译时错误,说“使用可能未分配的字段'Age'”但是如果我像这样创建一个结构的实例:

Person p = new Person();

然后我尝试访问p.Age我将得到0的值。现在幕后究竟发生了什么?运行时是否为我初始化这些变量,或者编译器在编译后放置在IL中初始化它们的代码?

编辑: 任何人都可以解释这种行为: 代码:

struct Person
{
    public string Name { get; set; }

}

如果我像这样创建struct的实例:

Person p;

我手动初始化名称

p.Name = "SomeRandomName"';

我将无法使用它。编译器给出错误“使用未分配的局部变量p”,但如果我使用默认(无参数)构造函数生成结构的实例,则不存在这样的错误。

3 个答案:

答案 0 :(得分:3)

会员不具备与当地人相同的规则。

在使用之前,必须显式初始化。成员由运行时初始化为各自的默认值。

如果您想了解更多相关信息:

在内部实现细节(非契约!)中,直到当前用于Windows对象的MS .NET运行时分配在堆上的预先归零的内存中(当它们完全在堆上时,课程)。所有默认值都是" physical"零,所以你需要的只是例如" 200个连续字节,值为0"。在许多情况下,这就像向操作系统询问预先归零的内存页面一样简单。它是保持内存安全的性能妥协 - 您只需执行Person即可轻松分配2000个new Person[2000]实例的数组,Person只需要{* 1}}字节的2000 *大小零;非常便宜,同时仍然保持安全的默认值。无需初始化2000 Person个实例,以及2000 int个实例和2000 string个实例 - 默认情况下它们全部为零。同时,您不可能获得string引用的随机值,该值将指向内存中的某个随机位置(非托管代码中的一个非常常见的错误)。

要求显式初始化本地化的主要原因是它可以防止愚蠢的编程错误。你永远不应该首先访问未初始化的值,如果你需要一个默认值,你应该明确它 - 默认值然后得到一个含义,意义应该是显式的。您会发现,首先您可以使用未初始化的本地有意义的情况非常罕见 - 您通常会在获取值的地方声明本地权限,或者您需要所有可能的分支来更新预先声明的本地无论如何。两者都可以更容易理解代码并避免愚蠢的错误。

答案 1 :(得分:1)

.NET中的每个数据类型都有一个默认值。对于所有引用类型,它都为null。对于特殊类型字符串,它也是null。对于所有值类型,它类似于零。对于布尔而言,这是假的,因为这相当于零。

使用成员字段编写类时,可以观察到相同的行为。构建完成后,即使在构造期间没有分配任何字段,所有这些字段都将具有默认值。

将struct用作成员时也是如此。由于struct不能为null,因此它也将被初始化,并且其所有成员(再次)都使用它们的默认值。

编译器输出的不同之处在于编译器无法确定您是否通过任何方式初始化了成员字段。但它可以确定您是否在读取之前设置了方法变量值。从技术上讲,这不是必要的,但由于它减少了编程错误(为什么你会读到一个你没有写过的变量?),会出现编译器错误。

答案 2 :(得分:1)

如果您浏览small struct documentation,可以引用:

  

struct类型是一种值类型,通常用于封装一小组相关变量,例如矩形的坐标或库存中项目的特征。

通常,当您在代码中声明这些value类型时:

int i; // By default it's equal to 0
bool b; // by default it's equal to false.

reference类型为:

string s; //By default it's null

您创建的struct是一种值类型,默认情况下不会初始化,您无法访问其属性。因此,您无法将其声明为:

Person p;

然后直接使用它 因此你得到了错误:

  

"使用可能未分配的字段'年龄'"

因为p仍未初始化。 这也解释了你问题的第二部分:

  

我无法使用它。编译器给出错误"使用未分配的局部变量p"但如果我使用默认(无参数)构造函数创建结构的实例,则不会出现这样的错误。

您无法直接指定p.Name = "something"的原因是因为p仍未初始化。

您必须创建结构的新实例

Person p = New Person(); //or Person p = default(Person);

现在,当您创建结构的新实例而不向struct属性赋值时会发生什么?他们每个人都会拥有它的默认值。例如Age = 0,因为它是int类型。