2011-08-27 33 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