可空值类型:C# 基础知识

小窍门

本文是了解至少一种编程语言并正在学习 C# 的开发人员的 “基础知识 ”部分的一部分。 如果你不熟悉编程,请先 学习入门 教程。 有关详细信息,请参阅语言参考中的可空值类型

可为 null 的值类型表示其基础值类型T?T的所有值,以及附加null值。 类型的 int? 变量包含任何整数或 null 表示“无值”。

值类型,例如 intboolDateTime,默认情况下不能保留 null。 此行为非常有效,可防止出现许多错误。 但是,当某个值可能真正不存在时,此限制会产生问题。 常见方案是从数据库读取的:整数列可能包含数字,或者它根本不包含任何值(NULL 在 SQL 中)。 普通 int 不能表示这种缺席,但 int? 可以。

声明可以为 null 的值类型

追加 ? 到任何值类型,使其可为 null:

int?    age      = null;    // integer with no value yet
double? price    = 9.99;    // nullable double with a value
bool?   isActive = null;    // boolean with no value

age = 30;                   // assign a value later

int?[] scores = [100, null, 85, null, 72]; // array with absent entries

可以为 null 的值类型的默认值是null,而不是其基础类型的默认值。

检查某个值是否存在

检查可为 null 的值类型并提取其值的建议方法是采用 类型模式

int? temperature = 72;

if (temperature is int degrees)
{
    Console.WriteLine($"Temperature is {degrees}°F.");
}
else
{
    Console.WriteLine("Temperature is not recorded.");
}
// Output: Temperature is 72°F.

模式is int degrees仅当temperature非null时匹配,同时将其值绑定到degrees。 您可以在一步中同时进行 null 检查和值提取。

或者,使用 HasValueValue 属性:

int? count = 42;

if (count.HasValue)
{
    Console.WriteLine($"Count is {count.Value}.");
}
else
{
    Console.WriteLine("Count has no value.");
}
// Output: Count is 42.

对新代码,首选 is T value 模式。 它引入了一个新的不可为 null 的变量,该变量的作用域限定于匹配分支,这样意图更加清晰,并消除了在 null 检查之外意外使用 Value 的任何风险,否则会引发 InvalidOperationException 异常。

还可以直接与 null 进行比较。

int? quantity = null;

if (quantity != null)
{
    Console.WriteLine($"Quantity: {quantity.Value}");
}
else
{
    Console.WriteLine("Quantity is not set.");
}
// Output: Quantity is not set.

获取具有回退功能的值

当需要从可为 null 的类型中提取不可为 null 的值时,请使用 GetValueOrDefault 运算符或 null 合并 ?? 运算符。

int? rating = null;

int result1 = rating.GetValueOrDefault();    // 0 (default for int)
int result2 = rating.GetValueOrDefault(-1);  // -1 (specified fallback)

Console.WriteLine(result1); // 0
Console.WriteLine(result2); // -1

rating = 5;
int result3 = rating.GetValueOrDefault(-1);  // 5 (actual value)
Console.WriteLine(result3); // 5

?? 运算符通常更简洁:

int? priority = null;

int effective = priority ?? 0;  // 0 because priority is null
Console.WriteLine(effective);   // 0

priority  = 3;
effective = priority ?? 0;      // 3 because priority has a value
Console.WriteLine(effective);   // 3

这两种方法在某个值存在时返回该值,当不存在值时返回您指定的回退值。

具有可为 null 的值类型算术

运算符针对可为 null 值类型的算术和比较操作进行了提升:当任一操作数为 null 时,结果为null,而不是产生错误。

int? a = 10;
int? b = 20;
int? c = null;

int? sum     = a + b;   // both non-null: result is 30
int? product = a * c;   // one operand is null: result is null

Console.WriteLine(sum);               // 30
Console.WriteLine(product.HasValue);  // False — null propagates through arithmetic

默认情况下,Null 通过算术传播。 为了防止 null 结果进一步传播,请在将其用于计算之前提取具有 ??GetValueOrDefault 的值。

另见