基元类型为何须要为null?考虑两个场景:数据库
1)数据库中一个int字段能够被设置为null。在C#中,值被取出来后,为了将它赋值给int类型,不得不首先判断一下它是否为null。若是将null直接赋值给int类型,会引起异常。服务器
2)在一个分布式系统中,服务器须要接收并解析来自于客户端的数据。一个int型数据可能在传输过程当中丢失或被篡改了,转型失败后应该保存为null值,而不是提供一个初始值。分布式
相似的场景还有不少,因此从.NET 2.0开始,FCL中提供了一个额外的类型:能够为空的类型Nullable<T>。它是一个结构体,声明以下:blog
[SerializableAttribute] public struct Nullable<T> where T : struct
由于是结构体,因此只有值引用类型才能够做为“能够为空的类型”(引用类型自己就能够为null)。一个能够为空的int类型表示为:class
Nullable<int> i = null;
它也能够表示为:基础
int? i = null;
语法T?是Nullable<T>的简写,二者能够相互转换。能够为 null 的类型表示其基础值类型正常范围内的值再加上一个null值。例如,Nullable<Int32>,其值的范围为-2 147 483 648 ~ 2 147 483 647,再加上一个null值。语法
如今来看看可空类型和基元类型的互相转换。基元类型提供了其对应的可空类型的隐式转换,以下所示:引用
int? i = null; int j = 0; i = j;
反过来,可空类型不可隐式转换为对应的基元类型,正确的转换形式以下:数据
int? i = 123; int j ; if (i.HasValue) { j = i.Value; } else { j = 0; }
可是,这段代码看上去是否是有点烦琐?因此,在阐述可空类型的时候,不得不提到??运算符。??最大的用处就是将可空类型的值赋值给对应的基元类型进行简化,上文代码的一个简化形式就是:客户端
int? i = 123; int j = i ?? 0;
int j = i ?? 0;表示的意思是,若是i的HasValue为true,则将i的value赋值给j;不然,就给j赋值为0。