CLR 如何在为结构分配 null 值时绕过引发错误

本文关键字:错误 null 分配 结构 CLR | 更新日期: 2023-09-27 18:36:03

我试图理解这段代码中的一件事:

Nullable<Int32> x = 5;
Nullable<Int32> y = null;
Console.WriteLine("x: HasValue={0}, Value={1}",  x.HasValue, x.Value);
Console.WriteLine("y: HasValue={0}, Value={1}",  y.HasValue, y.GetValueOrDefault());

输出为:

x: HasValue=True, Value=5
y: HasValue=False, Value=0

当你把null传递给y时,我不明白的事情,我相信它调用public static implicit operator Nullable<T>(T value)但是此方法的定义初始化了一个新的结构传递value,该结构被分配null但是构造函数方法不检查它是否为null,因此它可以default(T)分配给value

为什么我们甚至可以在这里将 null 分配给结构并且它工作正常?

你们能知道我在这里错过了什么吗?我不明白它是如何绕过null并返回默认值的。

可为空的代码内部定义:

http://codepaste.net/gtce6d

CLR 如何在为结构分配 null 值时绕过引发错误

相信它调用公共静态隐式运算符 Nullable(T 值)

不,它没有,因为在这种情况下T Int32,而null不是Int32。它只是将y变量保留为默认值,这意味着对于结构来说,所有字节都0。这将导致结构具有返回falseHasValue

您不能真正将null传递给结构,但 C# 编译器正在将其转换为默认初始化。

默认值在new Nullable<T>(value);调用的构造函数中分配(第 40 行)

我的猜测是,将null分配给可为空的会调用默认构造函数。这是hasValue保持false的唯一可能方式。

Nullable<T>只是一个结构,它有一个布尔字段指示它是否有值,还有一个字段(如果第一个字段为真)指示该值是什么。 实际上不可能将任何结构设置为nullNullable<T>也不例外。 相反,编译器将设置Nullable<T>的请求转换为null的请求,将"具有值"字段(反映在属性HasValue中)设置为 false,并将"实际值"字段(反映在属性Value中)设置为其类型的默认值。

就我个人而言,我认为假装HasValue是假的Nullable<T>null更令人困惑而不是有用,但我并不Microsoft。 我认为每个Nullable<T>类型都有一个静态属性Nullable<T>.Null会更有帮助(这相当于default(Nullable<T>),但是Nullable<T>的行为已经足够完善,我怀疑它永远不会改变。