C# - 可空类型
如你所知,值类型不能被赋空值。例如,`int i = null` 会导致编译时错误。
C# 2.0 引入了可空类型,允许你将 null 赋值给值类型变量。你可以使用 `Nullable
Nullable<int> i = null;
可空类型可以表示其基础值类型的正确值范围,外加一个额外的 _null_ 值。例如,Nullable
可空类型是 `System.Nullable
[Serializable]
public struct Nullable<T> where T : struct
{
public bool HasValue { get; }
public T Value { get; }
// other implementation
}
一个 `int` 类型的可空类型与普通的 `int` 加上一个标志(表示 `int` 是否有值,即是否为 null)是相同的。其余的都是编译器魔法,它将“null”视为一个有效值。
static void Main(string[] args)
{
Nullable<int> i = null;
if (i.HasValue)
Console.WriteLine(i.Value); // or Console.WriteLine(i)
else
Console.WriteLine("Null");
}
如果对象已赋值,`HasValue` 将返回 **true**;如果未赋值或已赋值为 null,则返回 **false**。
如果可空类型为 null 或未赋值,使用 NullableType.Value 访问值将抛出运行时异常。例如,如果 i 为 null,i.Value 将抛出异常。

使用 GetValueOrDefault() 方法可以获取实际值(如果它不为 null),如果为 null 则获取默认值。例如:
static void Main(string[] args)
{
Nullable<int> i = null;
Console.WriteLine(i.GetValueOrDefault());
}
可空类型的简写语法
你可以使用 '?' 运算符来缩写语法,例如 int?、long?,而不是使用 Nullable
int? i = null;
double? D = null;
?? 运算符
使用 '??' 运算符将可空类型赋值给非可空类型。
int? i = null;
int j = i ?? 0;
Console.WriteLine(j);
在上面的例子中,i 是一个可空整数,如果你将其赋值给非可空整数 j,那么如果 i 为 null,它将抛出运行时异常。因此,为了降低异常风险,我们使用了 '??' 运算符来指定如果 i 为 null,则将 0 赋值给 j。
赋值规则
可空类型具有与值类型相同的赋值规则。如果可空类型在函数中声明为局部变量,则在使用之前必须为其赋值。如果它是任何类的字段,则默认情况下其值为 null。
例如,下面的 int 类型的可空变量在未赋值的情况下声明和使用。编译器将给出 **“使用未赋值的局部变量 'i'”** 错误。

在下面的示例中,int 类型的可空变量是类的字段,因此不会出现任何错误。
class MyClass
{
public Nullable<int> i;
}
class Program
{
static void Main(string[] args)
{
MyClass mycls = new MyClass();
if(mycls.i == null)
Console.WriteLine("Null");
}
}
可空辅助类
null 被认为小于任何值。因此比较运算符不会与 null 进行比较。考虑以下示例,其中 i 既不小于 j,也不大于 j,也不等于 j。
static void Main(string[] args)
{
int? i = null;
int j = 10;
if (i < j)
Console.WriteLine("i < j");
else if( i > 10)
Console.WriteLine("i > j");
else if( i == 10)
Console.WriteLine("i == j");
else
Console.WriteLine("Could not compare");
}
Nullable 静态类是可空类型的辅助类。它提供了一个 compare 方法来比较可空类型。它还有一个 GetUnderlyingType 方法,该方法返回可空类型的基础类型参数。
static void Main(string[] args)
{
int? i = null;
int j = 10;
if (Nullable.Compare<int>(i, j) < 0)
Console.WriteLine("i < j");
else if (Nullable.Compare<int>(i, j) > 0)
Console.WriteLine("i > j");
else
Console.WriteLine("i = j");
}
可空类型的特性
- 可空类型只能与值类型一起使用。
- 如果值为 null,Value 属性将抛出 InvalidOperationException;否则,它将返回值。
- 如果变量包含值,HasValue 属性返回 true;如果为 null,则返回 false。
- 你只能使用 == 和 != 运算符与可空类型。对于其他比较,请使用 Nullable 静态类。
- 不允许嵌套可空类型。Nullable
> i; 将导致编译时错误。