可以为 Null 的值类型 (Visual Basic)

有时,你在某些情况下使用的值类型不具有定义的值。 例如,数据库中的字段可能必须在具有有意义的分配值和没有分配值之间进行区别。 值类型可以扩展为接受其正常值或 null 值。 此类扩展称为可以为 null 的类型。

每个可以为 null 的值类型都由泛型 Nullable<T> 结构构造。 考虑使用跟踪与工作相关活动的数据库。 下面的示例构造一个可以为 null 的 Boolean 类型,并声明该类型的变量。 你可以通过三种方式编写声明:

Dim ridesBusToWork1? As Boolean
Dim ridesBusToWork2 As Boolean?
Dim ridesBusToWork3 As Nullable(Of Boolean)

变量 ridesBusToWork 可以包含值 True、值 False 或根本不包含值。 它的初始默认值是没有任何值,在本例中,这可能意味着尚未获取此人的信息。 与此相反,False 可能表示信息已获得,并且此人不乘坐公共汽车上班。

可以使用可以为 null 的值类型声明变量和属性,并且使用可以为 null 的值类型的元素声明数组。 可以使用可以为 null 的值类型作为参数来声明过程,并且可以从 Function 过程中返回可以为 null 的值类型。

不能对引用类型(如数组、String 或类)构造可以为 null 的类型。 基础类型必须为值类型。 有关更多信息,请参见 Value Types and Reference Types

使用可以为 Null 的类型变量

可以为 null 的值类型的最重要成员是其 HasValueValue 属性。 对于可以为 null 的值类型的变量,HasValue 会告诉你变量是否包含已定义的值。 如果 HasValueTrue,则可以从 Value 中读取值。 请注意,HasValueValue 都是 ReadOnly 属性。

默认值

当使用可以为 null 的值类型声明变量时,其 HasValue 属性的默认值为 False。 这意味着,默认情况下,该变量没有定义的值,而不是其基础值类型的默认值。 在下面的示例中,变量 numberOfChildren 最初没有定义的值,即使 Integer 类型的默认值是0。

Dim numberOfChildren? As Integer

null 值用于指示未定义或未知的值。 如果已将 numberOfChildren 声明为 Integer,则不会有任何值指示信息当前不可用。

存储值

需要以典型方式将值存储在可以为 null 的值类型的变量或属性中。 下面的示例为前面示例中声明的变量 numberOfChildren 赋值。

numberOfChildren = 2

如果可以为 null 的值类型的变量或属性包含已定义的值,则可以使其恢复到未赋值的初始状态。 为此,可将变量或属性设置为 Nothing,如下例所示。

numberOfChildren = Nothing

注意

虽然可以将 Nothing 分配给可以为 null 的值类型的变量,但不能使用等号测试它是否为 Nothing。 使用等号 someVar = Nothing 的比较运算结果始终为 Nothing。 可以测试变量的 HasValue 属性是否为 False,或者使用 IsIsNot 运算符进行测试。

检索值

若要检索可为 null 的值类型的变量的值,应该首先测试其 HasValue 属性以确认它具有一个值。 如果尝试读取 HasValueFalse 时的值,Visual Basic 会引发 InvalidOperationException 异常。 下面的示例演示了读取前面示例中的变量 numberOfChildren 的建议方式。

If numberOfChildren.HasValue Then
    MsgBox("There are " & CStr(numberOfChildren) & " children.")
Else
    MsgBox("It is not known how many children there are.")
End If

比较可以为 Null 的类型

在布尔表达式中使用可以为 null Boolean 的变量时,结果可以是 TrueFalseNothing。 下面是 AndOr 的真值表。 由于 b1b2 现在具有三个可能的值,因此有九个计算组合。

b1 b2 b1 And b2 b1 Or b2
Nothing Nothing Nothing Nothing
Nothing True Nothing True
Nothing False False Nothing
True Nothing Nothing True
True True True True
True False False True
False Nothing False Nothing
False True False True
False False False False

当布尔变量或表达式的值为 Nothing 时,它既不是 true 也不是 false。 请看下面的示例。

Dim b1? As Boolean
Dim b2? As Boolean
b1 = True
b2 = Nothing

' The following If statement displays "Expression is not true".
If (b1 And b2) Then
    Console.WriteLine("Expression is true")
Else
    Console.WriteLine("Expression is not true")
End If

' The following If statement displays "Expression is not false".
If Not (b1 And b2) Then
    Console.WriteLine("Expression is false")
Else
    Console.WriteLine("Expression is not false")
End If

在此示例中,b1 And b2 的计算结果为 Nothing。 因此,在每条 If 语句中执行 Else 子句,输出如下所示:

Expression is not true

Expression is not false

注意

如果 AndAlsoOrElse 使用短路计算,则必须在第一个计算结果为 Nothing 时计算其第二个操作数。

传播

如果算术、比较、移位或类型运算的一个或两个操作数是可以为 null 的值类型,则运算的结果也是可以为 null 的值类型。 如果两个操作数的值都不是 Nothing,则对操作数的基础值执行运算,就像两者都不是可以为 null 的值类型一样。 在下面的示例中,变量 compare1sum1 是隐式类型。 如果将鼠标指针停留在它们上方,则会看到编译器将为这两个值推断出可为 null 的值类型。

' Variable n is a nullable type, but both m and n have proper values.
Dim m As Integer = 3
Dim n? As Integer = 2

' The comparison evaluated is 3 > 2, but compare1 is inferred to be of 
' type Boolean?.
Dim compare1 = m > n
' The values summed are 3 and 2, but sum1 is inferred to be of type Integer?.
Dim sum1 = m + n

' The following line displays: 3 * 2 * 5 * True
Console.WriteLine($"{m} * {n} * {sum1} * {compare1}")

如果一个或两个操作数的值都为 Nothing,则结果将为 Nothing

' Change the value of n to Nothing.
n = Nothing

Dim compare2 = m > n
Dim sum2 = m + n

' Because the values of n, compare2, and sum2 are all Nothing, the
' following line displays: 3 * <null> * <null> * <null>
Console.WriteLine($"{m} * {If(n, "<null>")} * {If(sum2, "<null>")} * {If(compare2, "<null>")}")

对数据使用可以为 Null 的类型

数据库是使用可以为 null 的值类型的最重要的地方之一。 目前并不是所有的数据库对象都支持可以为 null 的值类型,但是设计器生成的表适配器支持。 请参阅 TableAdapter 支持可以为 null 的类型

请参阅