VB.NET:布尔值来自'Nothing',有时为'false',有时为Nullreference异常
我来自美国,我想知道为什么:VB.NET:布尔值来自'Nothing',有时为'false',有时为Nullreference异常,.net,vb.net,.net-3.5,compiler-construction,casting,.net,Vb.net,.net 3.5,Compiler Construction,Casting,我来自美国,我想知道为什么: 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,Boole
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))
。我认为这是因为编译器使用了一个helper函数,但这不是我的主题
为什么将Nothing
强制转换为Boolean
会计算为False
,而将Nothing
的对象强制转换为Boolean
会引发空引用异常?这有意义吗
[Option Strict ON]
这大概是因为在VB.NET中与C#中的
null
不完全相同
对于值类型,Nothing
表示该类型的默认值。对于布尔值
,默认值为False
,因此转换成功
值类型(如Integer或structures)与引用类型(如Form或String)之间的主要区别之一是引用类型支持空值。也就是说,引用类型变量可以不包含任何值,这意味着该变量实际上并不引用某个值。相反,值类型变量总是包含一个值。整数变量始终包含一个数字,即使该数字为零。如果将值Nothing分配给值类型变量,则值类型变量只会被分配其默认值(对于Integer,默认值为零)。在当前CLR中,无法查看整型变量并确定它是否从未被赋值-它包含零并不一定意味着它没有被赋值。
– EDIT:为了进一步澄清,第二个示例在运行时抛出
NullReferenceException
的原因是CLR试图将对象
(引用类型)取消绑定到布尔值
。当然,这会失败,因为对象是用空引用初始化的(将其设置为Nothing
):
请记住,正如我上面解释的,VB.NET关键字Nothing
在引用类型方面仍然与C#中的null
工作方式相同。这就解释了为什么会出现NullReferenceException
,因为您试图强制转换的对象实际上是一个空引用。它根本不包含值,因此不能取消绑定为布尔类型
当您尝试将关键字Nothing
强制转换为布尔值时,您不会看到相同的行为,即:
Dim b As Boolean = DirectCast(Nothing, Boolean)
因为关键字Nothing
(这一次,在值类型的情况下)仅表示“此类型的默认值”。如果是布尔值
,则为假
,因此强制转换是逻辑和直接的。使用关键字(文字)无
,与使用值为无
的引用变量之间存在差异
- 在VB.NET中,文字(关键字)得到特殊处理。
Nothing
关键字可以使用该类型的默认值自动转换为值类型
- 值为
无
的引用变量是不同的。你没有特殊的行为
- 文档中说“需要两个参数的数据类型之间的继承或实现关系”
- 显然,
对象
不会继承或实现布尔值
,除非将装箱的布尔值
放入对象变量中
因此,下面的代码在运行时失败,出现了一个异常
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean)
要获得预期的行为,您需要以下代码:
Dim b As Boolean?
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean?)
字符?
的意思是可为空(of)
这里有几件事你必须意识到
第一个是其他人已经指出的:Nothing
可以由VB编译器简单地解释为Boolean
值False
,给定适当的上下文,例如Dim b as Boolean=Nothing
这意味着当编译器看到以下内容时:
b = DirectCast(Nothing, Boolean)
它看到一个文本(Nothing
),还看到您希望将该文本用作布尔值。这使它成为一个不需要动脑筋的问题
但现在你必须意识到第二件事<对象上的code>DirectCast
本质上是一种取消装箱操作(对于值类型)。因此,从VB编译器的角度来看,需要发生的事情是:该框中必须有一个布尔值,否则操作将失败。因为实际上盒子里什么都没有,而这一次我们实际上什么都没说,比如在null
-它抛出了一个异常
如果我将此代码翻译为C#,它将如下所示:
bool b;
object obj = null;
b = (bool)default(bool);
b = (bool)obj;
希望这能让事情变得更清楚一些?我发现将布尔变量与字符串“True”、“False”或“Is nothing”进行比较似乎可以确保得到正确的比较。我使用一个函数返回一个div的html字符串,其中包含一个选中或未选中单选按钮的图像,并且没有任何内容返回为false。使用variable=“True”或“False”字符串并对进行最后一次检查对解决该问题毫无帮助
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
Dim b作为布尔值=无
response.write CheckValue(b=“True”)
response.write(b=“False”)
response.write(b什么都不是)
函数CheckValue(inVal为布尔值)为字符串
如果无效,那么
返回(“
其他的
返回(“
如果结束
端函数
当与字符串进行隐式比较时,系统似乎会转换为字符串,而使用.tostring方法只会创建一个错误,同时允许最后一次比较实际与nothingDim 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