2011-10-06 54 views
3

以下編譯在VB.NET(有選項嚴格ON)和輸出False爲什麼VB.NET中的三元運算符接受可空布爾值?

Dim b As Boolean? = Nothing 
Dim myString = If(b, "True", "False") 

爲什麼工作?

  • The documentation明確指出的If三個參數版本需要Boolean作爲第一個參數:

    參數1必需。布爾。確定要評估和返回哪些其他參數。

  • 並沒有隱式轉換從Boolean?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'. 
    

那麼,爲什麼這項工作?它是編譯器中的錯誤(或「隱藏功能」),還是文檔中的錯誤,Boolean?實際上是第一個參數If(a, b, c)的有效類型?

PS:在C#,b ? x : y確實編譯如果bbool?類型。


編輯:我reported this issue to Microsoft Connect。來自MS的某人已回覆並確認文檔將更新爲包含Boolean?的情況。

回答

4

有兩個「爲什麼是」。它爲什麼這樣做,爲什麼他們這樣做。我可以回答第一個,第二個是微軟的。

如果檢查使用反射從VB.Net生成的代碼,你會看到:

Dim b As Nullable(Of Boolean) = Nothing 
Dim myString As String = IIf(b.GetValueOrDefault, "True", "False") 

或C#:

bool? b = null; 
string myString = b.GetValueOrDefault() ? "True" : "False"; 

因此,編譯器本身插入GetValueOrDefaultNullable(of T)

+2

它真的使用IIF嗎? (注意兩個我)? –

+1

好的。我的Reflector被設置爲.Net 2.0,它沒有VB'IF'三元運算符。更新到4.0使得它'IF'而不是'IFF'。很明顯,這是Reflector嘗試從IL重建VB.Net。實際的IL命令是「brtrue.s」,它是「分支如果爲真」,這是三元操作通常轉換成的。 –

2

Docos的狀態是:

的操作。如果那個叫有三個參數的工作原理相似,但它使用短路計算綜合投資框架 功能。 IIf函數 總是評估其所有三個參數,而具有三個參數的If運算符 只評估其中兩個參數。第一個If如果 參數被評估,並且結果被轉換爲布爾值,True 或False。

它評估,然後鑄造。

EDIT1

有趣的地方是,在運行時,中投並沒有拋出異常。

+1

'第一個If參數被評估並且結果被轉換爲布爾值'...很好地被發現!有趣的是,它似乎並不是真的:'如果(0,1,2)'拋出'Option Strict On不允許從'Integer'到'Boolean'.'的隱式轉換,所以第一個參數不是* always * cast到一個布爾值。 – Heinzi

0

在處理空字符時,應始終使用.HasValue屬性,而不是僅引用可空字符。 VB有檢查,看看是否有物體已經被實例化或不使用時,下面的語法的遺產:

If Foo Then 
    ' Is instantiated 
End If 

其結果是,你的榜樣允許三元如果計算結果爲。我建議「修復」你的代碼是在這種情況下,多一點明確:

Dim b As Boolean? = Nothing 
Dim myString = If(b.HasValue, "True", "False") 

或者,而不是使用三元如果,爲什麼不把它改寫爲:

Dim myString = b.GetValueOrDefault(False).ToString() 
2

保持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... 
相關問題