来自 Basic boolean logic in 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)
CType(obj, Boolean)
会评估为False
(就像CBool(obj))
。我认为这是因为编译器使用辅助函数,但这不是我的主题。
为什么将Nothing
转换为Boolean
评估为False
,而将Nothing
的对象转换为Boolean
会抛出Nullreference-Exception?这有意义吗?
[Option Strict ON]
答案 0 :(得分:15)
据推测,这是因为VB.NET中的Nothing
与C#中的null
不完全相同。
对于值类型,Nothing
表示该类型的默认值。对于Boolean
,默认值为False
,因此投射成功。
值类型(如Integer)或结构和引用类型(如Form或String)之间的主要区别之一是引用类型支持空值。也就是说,引用类型变量可以包含值Nothing,这意味着该变量实际上并不引用值。相反,值类型变量始终包含值。 Integer变量始终包含一个数字,即使该数字为零。如果将值Nothing赋值给值类型变量,则只为值类型变量赋值为默认值(在Integer的情况下,默认值为零)。当前CLR中无法查看Integer变量并确定它是否从未被赋值 - 它包含零的事实并不一定意味着它没有被赋值。
- The Truth about Nullable Types and VB...
编辑:为了进一步说明,第二个示例在运行时抛出NullReferenceException
的原因是因为CLR正在尝试取消装箱Object
(引用类型) )到Boolean
。当然,这会失败,因为对象是使用空引用初始化的(将其设置为Nothing
):
Dim obj As Object = Nothing
请记住,正如我上面所解释的,当涉及到引用类型时,VB.NET关键字Nothing
仍然与C#中null
的工作方式相同。这就解释了为什么你得到一个NullReferenceException
,因为你试图投射的对象实际上是一个空引用。它根本不包含任何值,因此无法取消装箱到Boolean
类型。
当您尝试将关键字Nothing
强制转换为布尔值时,您看不到相同的行为,即:
Dim b As Boolean = DirectCast(Nothing, Boolean)
因为关键字Nothing
(这次,在值类型的情况下)只是意味着“此类型的默认值”。如果是Boolean
,那就是False
,因此演员阵容合乎逻辑且直截了当。
答案 1 :(得分:4)
你必须要在这里实现一些事情。
第一个是其他人已经指出的:Nothing
可以被VB编译器解释为Boolean
值{{ 1}}给出适当的上下文,例如False
。
这意味着当编译器看到这个时:
Dim b As Boolean = Nothing
它会看到文字(b = DirectCast(Nothing, Boolean)
)并且还会看到您要将此文字用作Nothing
。这使得它成为一个明智的选择。
但是现在这是第二个你需要意识到的事情。 Boolean
上的DirectCast
本质上是一个拆箱操作(对于值类型)。那么从VB编译器的角度来看,需要发生的是:需要在该框中成为Object
,否则操作将失败。因为实际上框中没有 nothing - 这次我们真的在讨论 nothing ,就像在Boolean
中一样 - 它会引发异常。
如果我要将此代码翻译成C#,它将如下所示:
null
希望这会让事情更清楚一点?
答案 2 :(得分:2)
使用关键字(文字)Nothing
和使用值为Nothing
的参考变量之间存在差异。
在VB.NET中,文字(关键字)Nothing
得到特殊处理。 Nothing
关键字可以使用该类型的默认值自动转换为值类型。
值为Nothing
的参考变量不同。你没有得到特殊的行为。
文档说DirectCast“需要两个参数的数据类型之间的继承或实现关系”。
显然Object
不会继承或实施Boolean
,除非您已将盒装Boolean
放入对象变量中。
因此下面的代码在运行时失败并出现异常。
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean)
答案 3 :(得分:1)
要获得预期的行为,您需要以下代码:
Dim b As Boolean?
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean?)
字符?
表示Nullable(of )
。
答案 4 :(得分:1)
我发现将布尔变量与“True”,“False”字符串进行比较或似乎无法确保我得到正确的比较。我正在使用一个函数返回一个div的html字符串,其中包含一个已检查或未选中的单选按钮的图像,并且没有任何回复的问题。使用变量=“True”或“False”字符串并使用IS NOTHING进行最后一次检查有助于解决该问题。
Dim b as boolean = nothing
response.write CheckValue(b = "True")
response.write (b = "False")
response.write (b is nothing)
Function CheckValue(inVal as boolean) as string
if inVal then
return ("<div><img src="checked.png" ></div>
else
return ("<div><img src="unchecked.png" ></div>
end if
end function
系统似乎在与字符串进行隐式比较时进行字符串转换,而使用 .tostring 方法只会创建错误,同时允许最后一次比较实际比较值 。
希望这有点帮助。它至少让我