为理解源代码而初始化的null

本文关键字:初始化 null 源代码 | 更新日期: 2023-09-27 18:25:26

我正在查看.NET Nullable<T>类的以下代码:http://referencesource.microsoft.com/#mscorlib/system/nullable.cs,ffebe438fd9cbf0e

我想知道,对于以下用途,它的行为会是什么:

int? x = null;

显然,x.hasValue()返回false,但是我看到在构造函数中,hasValue属性总是设置为true

那么我错过了什么?

为理解源代码而初始化的null

"构造函数",是的,是为Nullable<T>显式编写的构造函数,但是所有结构都有一个额外的构造函数,一个不允许实现的无参数默认构造函数。这将永远存在。

所以你可以把你的问题中的代码想象成类似这样:

int? x = new Nullable<int>();

事实上,如果我们编译您的代码和我的代码,并查看生成的IL:

您的代码:

IL_0001:  ldloca.s    00 // a
IL_0003:  initobj     System.Nullable<System.Int32>

我的代码:

IL_0001:  ldloca.s    00 // a
IL_0003:  initobj     System.Nullable<System.Int32>

所以它们完全相同。

结构的默认构造函数将所有字段初始化为逐字节的零,这相当于布尔字段为false,数字字段为0,引用类型字段为null等。

来自MSDN上的文档:

结构不能包含显式无参数构造函数。结构成员会自动初始化为其默认值。

这意味着总是有一个"默认的无参数构造函数"。你看不到它,但它总是在那里。如果传入T的值(该值不可为null),则构造函数可以假定它有一个值。

举个例子:

Nullable<int> c = new Nullable<int>();
Console.WriteLine(c.HasValue); // false
c = new Nullable<int>(1);
Console.WriteLine(c.HasValue); // true

C#以一种特殊的方式处理可为null的类型,而不是像常规的structs那样。

不可能将null分配给常规struct变量,但可以将其分配给Nullable<T>变量。为什么?它在C#语言规范的第6.1.5节中进行了描述

6.1.5空文字转换

存在从null文本到任何可为null的类型的隐式转换。此转换产生给定可为null类型的null值(§4.1.10)。

编译器将此转换实现为对Nullable<T>的默认无参数构造函数的调用。每个struct都有一个隐式无参数构造函数,它将所有字段初始化为默认值。bool的默认值为false