为什么会有所不同?!
Public Class Form1
Public Function MyFunction() As Integer?
Return Nothing
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim o As Object = Me
MsgBox(TypeName(Me)) ' Form1
MsgBox(TypeName(o)) ' Form1
MsgBox(TypeName(Me.MyFunction())) ' Nothing
MsgBox(TypeName(o.MyFunction())) ' Nothing
' but
MsgBox(TypeName(Me.MyFunction() + 0)) ' Nothing
MsgBox(TypeName(o.MyFunction() + 0)) ' Integer
End Sub
End Class
答案 0 :(得分:4)
使用Option Strict On
是一种避免这样的惊喜的好方法。你会得到一个“你想要做什么?”来自编译器的错误消息。
但是当它关闭时,这些是由DLR(动态语言运行时)执行的有效语句。哪个能够评估这样的后期绑定表达式。但是它有像Integer?
这样的可空类型的问题。它需要处理值的盒装版本。这简直就是没什么。并且没有任何类型信息与之相关。 DLR没有什么可以看到这开始是一个可以为空的整数生命,因为它知道它可能是字符串是Nothing。
编译器也无法帮助,它不能发出任何代码使表达式遵循正常的评估规则。它只知道有一些函数,它不知道哪个,其名称是“MyFunction”,不知道它返回的是什么类型的值。它将降压传递给DLR以对其进行排序。
所以DLR就是这样做的。并且它提出“不知道”+ 0 = 0.假设它 具有0的类型信息。它是一个整数,所以它也试图将左运算符解释为整数。哪个是有效的,没有什么是Integer的正确默认值。
功能,而不是错误。
答案 1 :(得分:2)
Visual Basic .NET在具有可空值类型之前已经有Nothing
了 - 它从pre-.NET Visual Basic继承了它。在某些情况下,它的行为更像是C#' default(T)
然后t null
。
您的最后一个调用是调用Visual Basic编译器服务中的AddObject
方法。这种方法已经存在了很长时间,并且再次提出了可以为空的值类型,并且遗憾的是没有很好地记录。
不幸的是,他们无法使可空类型的行为绝对一致,特别是面对后期绑定调用,同时仍然保持向后兼容性。例如,这也会打印0
:
Console.WriteLine(CType(CType(Nothing, Object), Int32))