VB.NET:来自`Nothing`的布尔值有时是`false`,有时是Nullreference-Exception

Tim*_*ter 8 .net vb.net compiler-construction casting .net-3.5

来自C#中的基本布尔逻辑,我想知道为什么:

Dim b As Boolean
Dim obj As Object = Nothing
'followig evaluates to False'
b = DirectCast(Nothing, Boolean)
'This throws an "Object reference not set to an instance of an object"-Exception'
b = DirectCast(obj, Boolean)
Run Code Online (Sandbox Code Playgroud)

A CType(obj, Boolean)会评估False(就像CBool(obj)).我认为这是因为编译器使用辅助函数,但这不是我的主题.

为什么铸造NothingBoolean的计算结果为False,而铸造的对象,是NothingBoolean抛出一个Nullreference的异常?那有意义吗?

[Option Strict ON]
Run Code Online (Sandbox Code Playgroud)

Cod*_*ray 15

据推测,这是因为Nothing在VB.NET中与nullC#完全不同.

对于值类型,Nothing表示该类型的默认值.在a的情况下Boolean,默认值为False,因此转换成功.

值类型(如Integer)或结构和引用类型(如Form或String)之间的主要区别之一是引用类型支持空值.也就是说,引用类型变量可以包含值Nothing,这意味着该变量实际上并不引用值.相反,值类型变量始终包含值.Integer变量始终包含一个数字,即使该数字为零.如果将值Nothing赋值给值类型变量,则只为值类型变量赋值为默认值(在Integer的情况下,默认值为零).当前CLR中无法查看Integer变量并确定它是否从未被赋值 - 它包含零的事实并不一定意味着它没有被赋值.
    - 关于可空类型和VB的真相......

编辑:为了进一步说明,第二个示例NullReferenceException在运行时抛出的原因是因为CLR正在尝试将Object(引用类型)解包到a Boolean.当然,这会失败,因为该对象是使用null引用初始化的(将其设置为等于Nothing):

Dim obj As Object = Nothing
Run Code Online (Sandbox Code Playgroud)

请记住,正如我上面所解释的,当涉及引用类型时,VB.NET关键字Nothing仍然与nullC#中的相同.这就解释了为什么你得到一个因为你试图投射的对象实际上是一个空引用.它根本不包含任何值,因此无法取消装入某个类型.NullReferenceExceptionBoolean

当您尝试将关键字强制Nothing转换为布尔值时,您看不到相同的行为,即:

Dim b As Boolean = DirectCast(Nothing, Boolean)
Run Code Online (Sandbox Code Playgroud)

因为关键字Nothing(这次,在值类型的情况下)仅仅意味着"此类型的默认值".在的情况下Boolean,这是False,这样的转换是合乎逻辑的和直接的.