可空值类型
一个值类型的变量永远不可能为null;它总是包含值类型的值本身。某些情况下会成为问题。如:数据库中的一个列可能允许值为空 ,为了与数据库中的列相对应,CLR引入了可空值类型 。
可空值类型FCL中的定义
[Serializable, StructLayout(LayoutKind.Sequential)] public struct Nullable<T> where T : struct { //这两个字段表示状态 private Boolean hasValue = false; //假定null internal T value = default(T); //假定所有比特都是零 public Nullable(T value) { this.value = value; this.hasValue = true; } public Boolean HasValue { get { return hasValue; } } public T Value { get { if (!hasValue) { throw new InvalidOperationException("Nullable object must have a value."); } return value; } } public T GetValueOrDefault() { return value; } public T GetValueOrDefault(T defaultValue) { if(!HasValue) return defaultValue; return value; } public override Boolean Equals(object other) { if(!HasValue) return (other == null); if(other == null) return false; return value.Equals(other); } public override int GetHashCode() { if(!HasValue) return 0; return value.GetHashCode(); } public override string ToString() { if(!HasValue) return ""; return value.ToString(); } public static implicit operator Nullable<T>(T value) { return new Nullable<T>(value); } }
在代码中使用可空类型
Nullable<Int32> x = 5; Nullable<Int32> y = null; Console.WriteLine("x:HasValue={0},Value={1}", x.HasValue, x.Value); Console.WriteLine("y:HasValue={0},Value={1}", y.HasValue, y.GetValueOrDefault());
C#对可空值类型的支持
- ?表示法声明初始化变量
c#提供了一个更清晰的语法来处理可空值类型。c#允许用问号表示法来声明并初始化变量。
Int32? a = 5;
Int32? b = null;
Int32?等价于Nullable<Int32> - 可空类型与操作符
一元操作符(++,+,-,--,!,~)操作数是Null,结果就是Null。
二元操作符(+,-,*,/,%,&,|,^,<<,>>) 两个操作数中任何一个是null,结果就是null。& ,| 操作符应用于Boolean?操作数的时候。
相等性操作符(==,!=) 两个操作数都是null ,两者相等,一个操作数为null,两者不相等,两个操作数都不为null,比较值来判断是否相等.
关系操作符(<,>,<=,>=) 两个操作数任何一个是null ,结果就是false。两个操作数都不是null 就比较值。 - 可空实例上执行转换和转型
Int32? a = 5;//从非可空的 Int32 转换为Nullable<Int32> Int32? b = null;//从null隐式转换为Nullable<Int32> Int32 c = (Int32)a;//从Nullable<Int32>强制转换为非可空的Int32 //在可空基元类型之间转型 Double? d = 5;//Int32 转型为Double? Double? e = b;//Int32? 转型为Double?
??空接合操作符
c#提供了一个所谓的“空接和操作符”,即??操作符,它要获取两个操作数,如果左边的操作数不为null,返回值为左边操作数的值。如果左边的操作数为 null,返回右边的操作数的值
Int32? b = null; int? c = 1; int a = 32; Console.WriteLine(b ?? a);//返回32 Console.WriteLine(c ?? a);//返回1
可空值类型的装箱
值类型转换为引用类型需要装箱。当CLR对一个Nullable<T>实例进行装箱时,先做null判断,如果是,CLR不进行装箱,直接返回null,如果实例不为null ,则同对待普通的值类型一样进行装箱过程
可空值类型的拆箱
CLR允许将一个已装箱的值类型T拆箱为一个T或者一个Nullabe<T>。如果对已装箱值类型的引用为null,CLR会将Nullabe<T>的值设为null。
可空值类型调用GetType
调用Nullable<T>类型的实例的GetType时,返回的类型是T,而不是Nullable<T>
Int32? a = 5; Console.WriteLine(a.GetType());//返回System.Int32 不是 System.Nullable<Int32>