为理解源代码而初始化的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
。
那么我错过了什么?
"构造函数",是的,是为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的类型,而不是像常规的struct
s那样。
不可能将null
分配给常规struct
变量,但可以将其分配给Nullable<T>
变量。为什么?它在C#语言规范的第6.1.5节中进行了描述
6.1.5空文字转换
存在从null文本到任何可为null的类型的隐式转换。此转换产生给定可为null类型的null值(§4.1.10)。
编译器将此转换实现为对Nullable<T>
的默认无参数构造函数的调用。每个struct
都有一个隐式无参数构造函数,它将所有字段初始化为默认值。bool
的默认值为false
。