三元运算符VB vs C#:为什么解决Nothing为零?

我只是在脚下射击,想知道是否有实际的理由让这种情况成为可能。
无论如何,这个问题可以留在未来的脚射手的方便。


假设我们在vb.net中有一个可以为null的值:

Dim i as Integer? 

我们希望根据条件为其分配值,并使用三元运算符,因为它非常简洁和东西:

 i = If(condition(), Nothing, 42) 

也就是说,如果条件为true ,则使用可空性,否则使用该值。
射击发生的时间点。 由于没有明显的原因,VB编译器决定NothingInteger的公共基类型是Integer ,此时它会以静默方式将语句转换为:

 i = If(condition(), 0, 42) 

现在,如果您要在C#中执行此操作:

 i = (condition()) ? null : 42; 

您会立即收到编译器错误,指出int不能很好地混合。 这很棒,因为这次我采用了C#方式,我的脚会更健康。 为了编译,你必须明确地写:

 i = (condition()) ? null : (int?)42; 

现在,您可以在VB中执行相同操作并获得正确的null-ness:

 i = If(condition(), Nothing, CType(42, Integer?)) 

但这需要首先拍摄你的脚。 没有编译器错误,也没有警告。 那就是Explicit OnStrict On


所以我的问题是,为什么?
我应该将其作为编译器错误吗?
或者有人可以解释为什么编译器会以这种方式运行?

这是因为VB的Nothing并不直接等同于C#的null

例如,在C#中,此代码将无法编译:

 int i = null; 

但是这个VB.Net代码运行得很好:

 Dim i As Integer = Nothing 

VB.Net的Nothing实际上与C#的default(T)表达式更接近。

三元运算符只能返回一种类型。

在C#中,它尝试选择基于null42的类型。 好吧, null没有类型,所以它决定三元运算符的返回类型是42 ; 一个普通的老int 。 然后它抱怨因为你不能将null作为普通的旧int返回。 当你强迫42作为一个int? ,三元运算符将返回一个int? ,所以null是有效的。

现在,我不知道VB,但引用了MSDN,
Assigning Nothing to a variable sets it to the default value for its declared type.

其中,由于VB确定三元运算符将返回一个int (使用与C#相同的进程), Nothing0 。 再次,强迫42成为一个int?Nothing变为int?的默认值int? ,如你所料,它是null

我认为这与IF有关,而与Nothing有关。 考虑以下代码:

 ''# This raises an exception Dim x As Integer? x = If(True, Nothing, Nothing) MessageBox.Show(x.Value) ''# As does Dim x As Integer? x = Nothing MessageBox.Show(x.Value) ''# Changing one of the truthpart arguments of If is what seems to return the zero. Dim x As Integer? x = If(True, Nothing, 5) MessageBox.Show(x.Value) 

为什么这样做我仍然不知道,这可能是VB团队的一个问题。 我不认为它与Nothing关键字或Nullable有关。

从MSDN中, Nothingnull不是一回事……

为变量赋值Nothing将其设置为其声明类型的默认值。

如果在Expression中提供值类型,则IsNothing始终返回False。

请记住int? 是可以为空的类型,但它仍然是值类型,而不是引用类型。

尝试将其设置为DbNull.Value而不是Nothing

在许多情况下, Nothing将转换为默认值。 要以与使用null相同的方式使用Nothing ,您需要将其强制转换为正确的可空类型。

 Dim str As String Dim int As Nullable(Of Integer) ' or use As Integer? Dim reader As SqlDataReader Dim colA As Integer = reader.GetOrdinal("colA") Dim colB As Integer = reader.GetOrdinal("colB") str = If(reader.IsDBNull(colA), DirectCast(Nothing, String), reader.GetString(colA)) int = If(reader.IsDBNull(colB), DirectCast(Nothing, Nullable(Of Integer)), reader.GetInt32(colB)) 

发生这种情况是因为Integer不是引用类型。 ‘Nothing’仅适用于参考类型。 对于值类型,分配Nothing会自动转换为默认值,如果是整数0。

这实际上现在可以通过使用New Integer在VS2015(至少)中实现吗?

例:

如果(testInt> 0,testInt,New Integer?),其中testInt的类型为Integer?