2011-08-27 62 views
4

我發現在VB.NET一個簡單的錯誤,可以很容易地複製:VB.NET如果(三元)錯誤

Dim pDate As Date? 
Dim pString As String = "" 

' works fine as expected 
pDate = If(False, "", Nothing) 

' expected: pDate will be set to Nothing. 
' BUG: Conversion from string "" to type 'Date' is not valid. 
pDate = If(False, pString, Nothing) 

'These both fail with the same error 
pDate = pString 
Dim pDate2 As Date? = "" 

問:這是一個錯誤?或者我或我的電腦有問題嗎? 如果這是一個錯誤,是否有這個錯誤報告(我似乎無法找到它)?

教訓:

  1. 這是不是一個錯誤
  2. 可空日期接受對象沒有
  3. 可空日期接受字符串沒有

pDate = Nothing ' ok. nullable date accepts object nothing 
pString = Nothing 
pDate = pString ' error. nullable date rejects string nothing 
+6

這是一個錯誤?你*不能*將'''''轉換爲'日期'。即使'If'(與'IIf'相反)在運行時只計算一邊並不意味着編譯器不檢測類型不匹配。 –

+1

是的,我知道編譯器仍然檢測到類型不匹配,但是(pDate =「」)是有效的,而(pDate = pString)不是(pString =「」) – Arvin

+0

pDate =「」如果Option嚴格或選項推斷開啓。 –

回答

5

bug是你的第一次使用If() ,而不是第二。與你的評論相反,結果沒有「預期」。那叫應該失敗,因爲「」不能轉換爲日期,並且三元運算符在所有級別都是類型安全的,不管表達式是否被使用。

我懷疑它是因爲編譯器優化而成功的:因爲一切都是文字,所以條件被優化了。第二次優化很難,因爲pString變量可能會被編譯器還不知道的另一個線程所改變。

與IL交互的人可能會證實這一點。

真正讓我感到驚訝的是,這只是在運行時才被捕獲。我希望編譯器注意到類型不匹配,並在該級別上投訴,而不是等到執行。你的VB選項設置可能與此有關。

+1

最有可能發生的事情是,常量摺疊發生在類型檢查之前。在檢查類型之前,第一個表達式被評估爲常量。由於'pString'不是一個常量,如果沒有在類型檢查後發生的數據流分析,它不能被優化。 – Gabe

+0

第四課:「三元操作符在所有級別都是類型安全的,無論表達式是否被使用。」 – Arvin

3

這很有趣。上面的例子非常清楚,有一些奇怪的事情發生。也就是說,Stack Overflow並不是真正的「報告」錯誤的好地方。如果您認爲自己確實發現了錯誤,則可以將您的發現發佈到Microsoft connect

我在連接上做了一個搜索,並且VB.NET和C#三元運算符都有很多怪癖,尤其是涉及Nullable值類型的時候。這可能只是另一個呢?

對於它的價值,你甚至可以簡化的情況下是這樣的:

Dim pDate As Date? 
pDate = If(False, "", Nothing) ' Works fine 
pDate = If(False, String.Empty, Nothing) ' Doesn't work 

值得注意的是,每一個出現的情況被打破(所有情況下預期的""使用)確實工作當行看起來像:pDate = If(False, String.Empty, CType(Nothing, Date?))

另外,Option Strict [On|Off]在這發揮了很大的作用。當設置Option Strict On時,所有這些都是編譯錯誤。此行爲只能在Option Strict Off時才能看到。我放在一起an example of all the situations here

最後,我不認爲這真的是一個錯誤,但只是使用Option Strict Off的一個缺陷之一。這看起來很奇怪(不合邏輯),但是Option Strict Off也是如此。;)

+1

默認情況下,Option Strict在VB中關閉,這就是爲什麼在這裏發生任何奇怪的唯一原因。如果打開,兩行都會(或應該)拋出編譯器錯誤。 – Tridus