主要介绍为什么需要可空类型,如果C#语言不提供可空类型,我们可以有哪些解决方案、C#中的可空类型以及其简化语法
一、 为什么需要可空类型
引用类型如果没有通过构造函数初始化,则会指向空,其值为null,在内存中会有一块被置为0。
但是值类型却不能为空,它一定有一个默认值,因为值类型的值就是它本身,所以不会为空。
1. 但是有些时候,默认值也可能是一个有意义的值,而不是开发者想要的空值,比如表示数的默认值为0(C、C++中,如果变量是全局变量或静态变量,则默认值为0,在函数中的局部变量则是当前指向内存的值,即一个随机值),但0并不是空。
2. 有了空类型的话,在数据库中也能更好的适应。
所以我们需要一个可空类型,它的值是无,就像引用类型一样。
二、如果C#语言不提供可空类型,我们可以有哪些解决方案
1. 魔值,如果值类型的值等于一个特殊值,如-1000,则表示当前值为空,这种方法比较简单,但是需要牺牲一个值。
2. 借助标志位,将该值类型与一个bool型值绑定,如果bool为true,则该值类型不为空,这种方法一个会增加数据量,一个是很容易出错。为了解决不容易出错的问题,可以将两者结合成一个结构体,因为结构题也是值类型,不存在装箱拆箱的操作,但是还是没有解决会增加数据量的问题。
3.借助引用类型, 建立一个引用类型,如,一个类,这个类只维护这一个值,在构造函数中就会给该值赋值,这样就把值类型是否为空转化成了类是否为空。但是这样其实需要在托管堆中开拓内存,还是增加了代码量,增加了维护成本。
于是,C#为我们创建了一个可空类型。
三、C#中的可空值类型以及其简化语法
C#的可空值类型为Nullable<T>,它本身是值类型,所以它的实例分配在栈上,而且约束T必须是值类型,因为引用类型本身可以表示空值。它与T相比多了一个Bool(所以和结构体分装两个变量有什么区别?)而且提供了一些函数可以返回当前值或者如果值就返回默认值。判断当前值是否为空。
使用的方法:Nullable<int32> i=null;
bool flag=i.HasValue();
其声明的简化写法为:
T? i=null;
就是在类型名后面加个?
此外,以一般的值类型一样,他可以进行算术运算符、比较运算符以及逻辑运算符的运算,结果很容易是null。
四、 ??空接合操作符与as操作符
??与三元运算符里的?很相似,但是??运用与引用类型与可空值类型,主要判断值是否为null,使用方法为:
a=i??99;
这个式子的意思是i是否为Null,如果不是,则返回i,如果是,则返回99。
as运算符原本是作用于引用类型的,可空值类型出来后也可作用于可空值类型,它可将引用类型与可空值类型之间互相转换。
五、可空值类型的装箱拆箱
上面说的as操作符,其实就涉及到可空值类型的的装箱与拆箱。
除了使用as进行转换,也可以显示强制类型转换。
可空值类型装箱成引用类型时,如果没有值,则引用类型也为null。
要注意的是,如果将一个空引用拆箱成普通的值类型,则会运行报错,无引用异常。