为什么VB.NET中的三元运算符接受可为空的布尔值?
以下内容在VB.NET中编译(选项Strict On)并输出为什么VB.NET中的三元运算符接受可为空的布尔值?,vb.net,ternary-operator,Vb.net,Ternary Operator,以下内容在VB.NET中编译(选项Strict On)并输出False: Dim b As Boolean? = Nothing Dim myString = If(b, "True", "False") 为什么会这样 明确指出,If的三参数版本需要一个Boolean作为第一个参数: 需要论证1。布尔型。确定要计算和返回的其他参数 而且没有从布尔值?到布尔值的隐式转换: Dim b1 As Boolean? = Nothing Dim b2 As Boolean = b1 ' Fail
False
:
Dim b As Boolean? = Nothing
Dim myString = If(b, "True", "False")
为什么会这样
- 明确指出,
的三参数版本需要一个If
作为第一个参数: 需要论证1。布尔型。确定要计算和返回的其他参数Boolean
- 而且没有从
到布尔值?
布尔值的隐式转换:
Dim b1 As Boolean? = Nothing Dim b2 As Boolean = b1 ' Fails with the following error: ' Option Strict On disallows implicit conversions ' from 'Boolean?' to 'Boolean'.
布尔值?
实际上是的第一个参数的有效类型,如果(a,b,c)
附言:在C#中,b?如果b
类型为bool?
,则x:y
不会编译
编辑:我已经完成了。MS的人员已回复并确认文档将更新为包含
Boolean?
案例。Docos声明:
使用三个参数调用的If运算符的工作方式与IIf类似
功能,但它使用短路评估。IIf函数
始终计算其所有三个参数,而If运算符
它有三个参数,只计算其中的两个。第一个如果
参数进行求值,结果转换为布尔值True
或者是假的
它进行求值,然后进行强制转换
EDIT1
有趣的是,在运行时,cast没有抛出异常 处理可空值时,应始终使用.HasValue属性,而不仅仅是引用可空值。VB在检查对象是否已实例化时使用了以下语法:
If Foo Then
' Is instantiated
End If
因此,您的示例允许评估三元If。在这种情况下,我建议您将代码“修复”得更明确一些:
Dim b As Boolean? = Nothing
Dim myString = If(b.HasValue, "True", "False")
或者,与其使用三元If,不如将其改写为:
Dim myString = b.GetValueOrDefault(False).ToString()
有两个“为什么”。为什么会这样,为什么他们会这样做。我可以回答第一个,第二个是微软的
如果使用Reflector检查从VB.Net生成的代码,您将看到:
Dim b As Nullable(Of Boolean) = Nothing
Dim myString As String = IIf(b.GetValueOrDefault, "True", "False")
或C#:
因此,编译器本身正在为
null(of T)
插入GetValueOrDefault
,让ildasm.exe在遇到类似问题时随时可用。编译器使用Nullable(Of T).GetValueOrDefault()。官方语言规范并不禁止这样做。另外,这也不能说明这一点,这并不罕见
IL_0001: ldloca.s b
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0009: ldloca.s b
IL_000b: call instance !0 valuetype [mscorlib]System.Nullable`1<bool>::GetValueOrDefault()
IL_0010: brtrue.s IL_0019
etc...
IL_0001:ldloca.s b
IL_0003:initobj valuetype[mscorlib]系统。可为null`1
IL_0009:ldloca.s b
IL_000b:调用实例!0 valuetype[mscorlib]系统。可为null的`1::GetValueOrDefault()
IL_0010:brtrue.s IL_0019
等
它真的使用IIF吗?(注意两个I)?接得好。我的Reflector被设置为.NET2.0,它没有VBIF
trialer操作符。更新到4.0使其成为IF
而不是IFF
。显然,这是Reflector试图从IL重建VB.Net。实际的IL命令是brtrue.s
,它是“branch if true”,这是三元运算通常转换为的。计算第一个if参数,并将结果转换为布尔值。。。漂亮的斑点!有趣的是,这似乎不是真的:如果(0,1,2)
抛出选项Strict On,则不允许从“整数”到“布尔”的隐式转换。
,因此第一个参数并不总是转换为布尔值。
IL_0001: ldloca.s b
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0009: ldloca.s b
IL_000b: call instance !0 valuetype [mscorlib]System.Nullable`1<bool>::GetValueOrDefault()
IL_0010: brtrue.s IL_0019
etc...