27

我只是朝自己的脚开枪,想知道是否有真正的理由使这种情况成为可能。
而且无论如何,为了方便未来的射手,这个问题可以保留。


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

Dim i as Integer?

我们想为它分配一个值,基于一个条件,并使用三元运算符,因为它是如此整洁和东西:

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

也就是说,如果条件是true,则使用可空性,否则使用值。
在这一点上发生了枪击事件。没有明显的原因,VB 编译器决定 and 的通用基本类型NothingIntegerInteger此时它默默地将语句转换为:

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

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

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

你会立即得到一个编译器错误,说它<null>不能很好地与int. 这很好,因为如果我这次采用 C# 方式,我的脚会更健康。要编译它,您必须显式编写:

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

现在,您可以在 VB 中执行相同的操作并获得您期望的正确空值:

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

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


所以我的问题是,为什么?
我应该把它当作编译器错误吗?
或者有人可以解释为什么编译器会这样吗?

4

7 回答 7

35

这是因为 VBNothing不直接等同于 C# 的null.

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

int i = null;

但是这个 VB.Net 代码工作得很好:

Dim i As Integer = Nothing

VB.NetNothing实际上更接近 C# 的default(T)表达方式。

于 2010-11-10T17:40:27.803 回答
12

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

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

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

其中,由于 VB 确定三元运算符将返回一个int(使用与 C# 相同的过程),Nothing因此是0. 同样,将 强制转换42为的默认值,即,正如您所期望的那样。int?Nothingint?null

于 2010-11-10T17:53:51.467 回答
2

Nothing并且null不是一回事......来自MSDN:

将 Nothing 分配给变量会将其设置为其声明类型的默认值。

如果在 Expression 中提供值类型,IsNothing 总是返回 False。

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

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

于 2010-11-10T17:48:06.937 回答
2

我认为这与 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 无关。

于 2010-11-10T18:06:08.707 回答
1

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

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))
于 2013-06-29T08:34:40.550 回答
-1

发生这种情况是因为 Integer 不是引用类型。'Nothing' 仅适用于引用类型。对于值类型,分配 Nothing 会自动转换为默认值,即在整数 0 的情况下。

于 2010-11-10T17:49:11.707 回答
-1

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

前任。:

If(testInt> 0, testInt, New Integer?), testInt 是 Integer 类型吗?

于 2017-12-06T21:51:47.980 回答