1.什么是可空类型
可以为 null 的类型是 System.Nullable<T> 结构的实例。
可以为 null 的类型可表示一个基础类型的所有值 T,还可以再表示一个 null 值。 基础类型 T 可以是任何不可为 null 的值类型。 T 不能是引用类型。
例如,可以将 null 或任何整数值(从 Int32.MinValue 到 Int32.MaxValue)赋给 Nullable<int>,并可将 truefalse 或 null 赋给Nullable<bool>。
需要表示基础类型的未定义的值时,请使用可以为 null 的类型。 布尔变量只能有两个值:true 和 false。 没有“未定义”的值。
在许多编程应用程序中,尤其是数据库交互中,变量值可能未定义或缺失。 例如,数据库中的字段可能包含值 true 或 false,但它也可能根本不包含任何值。 这种情况下要使用 Nullable<bool> 类型。
可以为 null 的类型具有以下特征:
- 可以为 null 的类型表示可以向其赋与 null 值的值类型变量。 不能根据引用类型创建可以为 null 的类型 (引用类型已支持 null 值)。
- 语法 T? 是 Nullable<T> 的简写。 这两种形式是可互换的。
- 向可以为 null 的类型赋值的方法与向基础值类型赋值的方法相同:int? x = 10; 或 double? d = 4.108;。 还可赋予 null 值:int? x = null;。
- 使用 Nullable<T>.HasValue 和 Nullable<T>.Value 只读属性可测试是否存在 null 值并检索值,如以下示例所示:if (x.HasValue) y = x.Value;
- 如果变量包含值,则 HasValue 属性返回 true;如果值为 null,则返回 false。
- 如果 HasValue 返回 true,则 Value 属性返回值。 否则会引发 InvalidOperationException。
- 还可将 == 和 != 运算符用于可以为 null 的类型,如以下示例所示:if (x != null) y = x.Value; 如果 a 和 b 均为 null,则 a == b 的计算结果为 true。
- 从 C# 7.0 开始,可以使用模式匹配来检查和获取可以为 null 的类型的值:if (x is int valueOfX) y = valueOfX;。 T? 的默认值是一个实例,其 HasValue 属性返回 false。
- 使用 GetValueOrDefault() 方法可返回赋予的值,如果可以为 null 的类型的值为 null,它还可返回基础值类型的默认值。
- 使用 GetValueOrDefault(T) 方法可返回赋予的值,如果可以为 null 的类型的值为 null,它还可返回提供的默认值。
- null 合并运算符 ??,基于可以为 null 的类型的值向基础类型赋值:int? x = null; int y = x ?? -1;。 在示例中,由于 x 为 null,所以 y 的结果值为 -1。
- 如果定义了(用户定义的)两种数据类型之间的转换,还可将同一转换用于这些数据类型的可为 null 的版本。
- 不得嵌套可以为== null 的类型。 不会编译下面的一行代码:Nullable<Nullable<int>> n;
2.可空类型的装箱拆箱
可通过以下规则将可以为 null 的值类型装箱:
- 如果 HasValue 返回 false,则生成空引用。
- 如果 HasValue 返回 true,则基础值类型 T 的值将装箱,而不对 Nullable<T> 的实例进行装箱。
可将已装箱的值类型取消装箱到相应的可以为 null 的类型,如以下示例所示:
int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");
object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41
3.Null 合并运算符( ?? )
Null 合并运算符用于定义可空类型和引用类型的默认值。Null 合并运算符为类型转换定义了一个预设值,以防可空类型的值为 Null。Null 合并运算符把操作数类型隐式转换为另一个可空(或不可空)的值类型的操作数的类型。
如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。下面的实例演示了这点:
using System;
namespace CalculatorApplication
{
class NullablesAtShow
{
static void Main(string[] args)
{
double? num1 = null;
double? num2 = 3.14157;
double num3;
num3 = num1 ?? 5.34; // num1 如果为空值则返回 5.34
Console.WriteLine("num3 : {0}", num3);
num3 = num2 ?? 5.34;
Console.WriteLine("num3 : {0}", num3);
Console.ReadLine();
}
}
}
num3: 5.34
num3: 3.14157
4.Null条件运算符(?.)
Null条件运算符可用于空值检查操作
// 当customer.oeder不为空时,继续执行Count(),否则返回null
int? count = customer.oeder?.Count();
或者用于触发事件
OnChanged?.Invoke(this, args);
5.bool? 类型
可以为 null 的类型 bool? 可包含三个不同的值:true、false 和 null。 bool? 类型类似于在 SQL 中使用的布尔变量类型。
为确保 & 和 | 运算符产生的结果与 SQL 中具有三个值的布尔值类型一致,在此提供以下预定义运算符:
- bool? operator &(bool? x, bool? y)
- bool? operator |(bool? x, bool? y)
由下表定义这些运算符的语义:
x | y | 与运算 | 或运算 |
---|---|---|---|
true | true | true | true |
true | false | false | true |
true | null | null | true |
false | true | false | true |
false | false | false | false |
false | null | false | null |
null | true | null | true |
null | false | false | null |
null | null | null | null |