This article is currently in the process of being translated into Chinese (~93% done).
Nullable types
NULL的字面意思就是啥也没有 - 就是变量还没有赋值。通过本教程之前的介绍,大家应该已经处理过未初始化的变量,不管是有意的还是无意的 - 因此,应该清楚在访问一个变量的值前要先确认此变量有值。否则,结果只能得到一个NullReferenceException异常。
使用自己定义的对象及字符串时尤其要注意NULL值相关的问题。另一方面,对于数字值,比如,integer,永远都会有一个(默认)值 。对于integer,默认/回滚值 是0(零),不要把其与NULL混淆 - 它们完全不一样,虽然有些非静态类型的编程语言会把它们当做一样的东西来处理。0是一个数字 - NULL是啥也没有。
因此,如果想得到一个代表未定义/NULL值的的数字,那是办不到的,因为没法把null值赋给integer变量。当然,除非把这个integer变量定义为nullable (可为空的)- 专为此种情况而准备的一个特殊的语言结构。通过在类型名称后面加一个问号来把变量定义成可为空的。以下例子演示了两者的差异:
int notNullable = null; // Will cause an error from the compiler
int? nullable = null; // Just fine - it's nullable!这样的语法对于所有所谓的值类型,如 integer,float,bool和struct,都是合法的。而字符串和对象都是引用类型,就不能被定义为可为空的(nullable ),因为它们默认就是可为空的(nullable )。
检查nullable变量是否为空
定义了值可能为空的的变量后,检查其值是否真的为空显然就很重要了。有两种方法:简单地象与其它类型进行比较一样把变量与null关键字进行比较,或使用nullable对象从System.Nullable继承的HasValue属性。示例如下:
int? nullable = null;
if (nullable == null)
Console.WriteLine("It's a null!");
if (!nullable.HasValue)
Console.WriteLine("It's a null!");两者结果是一样的,因此程序员可随意选择任何一种他觉得最方便阅读和理解的方式。由于变量值可以为空,因此使用前都应该检查一下 - 否则就可能导致异常。
使用nullable值
nullable还从System.Nullable类继承了Value属性。这个属性可用于取得nullable对象的实际值。不过,对于简单的比较操作,如,使用==和!==操作符,C#允许省略Value属性,直接比较nullable对象本身。换言之,以下例子实现的功能是一样的:
int? nullable = 42;
if (nullable.Value == 42)
Console.WriteLine("It's 42!");
if (nullable == 42)
Console.WriteLine("It's 42!");nullable对象总是来自一种基础数据类型,如,之前例子中使用的integer。虽然这些数据类型都有各自的默认值,nullable对象的默认值总是null。这也就如前面介绍的那样,在使用nullable对象值之前必需检查其是否为null的原因。不过nullable类型继承了一个非常有用的方法:GetValueOrDefault()。此方法会返回nullable对象的值,如果有值的话,否则就返回其基础数据类型的默认值。因此,对于可为空的整数,会返回0,对可为空的布尔类型会返回false,等等。这使得检查和取值可以在单个表达式中完成:
if ((nullable.HasValue) && (nullable.Value == 42))
Console.WriteLine("It's 42!");
if(nullable.GetValueOrDefault() == 42)
Console.WriteLine("It's 42!");如上例所示,后一个语句更短且好理解,同时又实现了同样的功能。
总结
C#中的值类型,如整数和布尔值,都有默认值。如果希望绕开此默认值,如,需要区分0和null值,或需要确定用户是否明确地为某决定选择了“false”还是变量值仅仅是默认的false值,就可以在类型名称后面加上?(问号)把变量定义为nullable。