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

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

每个可以为 null 的值类型都是从泛型 Nullable<T> 结构构造的。 请考虑跟踪与工作相关的活动的数据库。 以下示例构造一个可为空的 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 的类型。 基础类型必须是值类型。 有关详细信息,请参阅 值类型和引用类型

使用可以为 Null 的类型变量

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

默认值

声明具有可为 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 的类型

在布尔表达式中使用可为 Boolean null 的变量时,结果可以是 TrueFalse也可以 Nothing。 下面是AndOr的真值表。 由于 b1b2 现在有三个可能的值,因此有 9 种组合需要评估。

b1 b2 b1 和 b2 b1 或 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. 因此,Else 条款在每个 If 语句中执行,输出如下所示:

Expression is not true

Expression is not false

注释

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

传播

如果算术、比较、移位或类型运算的一个或两个作数都是可为 null 的值类型,则该运算的结果也是可为 null 的值类型。 如果两个操作数都具有非 Nothing 的值,那么对操作数的实际值执行操作,就像两者都不是可空值类型那样。 在下面的示例中,变量 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 的类型的支持

另请参阅