C#2.0之可空类型
可空类型Nullable<T>
在C#2.0之前 ,值类型一直不可以为null,但是实际开发中常常会有这样的需求,比如结束时间。
为什么不可以为null
对于引用类型来说,null代表着空引用。就像href中的javaScirpt:,在内存中这一区域会全部用零表示,在GC的时候也会更加的轻松,对于值类型来说零是一个有效值 。
当然也有相应的替代方式
魔值
犧牲一个我们似乎永远也用不到的值 ,比如maxValue。但是这样做是非常的不优雅的
使用标志位
一个值类型对应着一个bool的变量,false表示没有值,true表示有值 。这看起来还不错,但是要维护两份变量
使用引用类型
object是所有类型的基类,同时它也是引用类型。但是这样会有着反復的拆箱与装箱,这也并不是我们所想要的
C#2.0使用了Nullable<T>
这种解決方式非常的优美,Nullable<T>是一个泛型的结构体。首先限制了T必须为struct类型。
这样问题又来了,Nullable也是值类型,为什么会可以为null呢。其实这只是C#玩的一个小花招而已,下面我来写一个简易版本的MyNullable<T>
可以看下面MyNullable<T>的代码了,HasValue是bool默认是false。如果通过構造函數斌值那么就是true了。
下面是測試用例,x获取value会报异常nullable Object mush have a value,而y则不会。
而C#中我们甚至可以直接为Nullable<T>賦值为null,这就是編譯器和CLR做的小花招了,如果反編譯就会看到它的真实面貌。而之后的版本里,又增加了各种各样的語法糖,比如与null进行对比(重写了Equals方法)以及使用int?这样更直观的方式进行声明
比较的问题
一个nullInt与nullInt进行比较时,>=竟然永远是false。毕竟 null 也 应该等于null 嘛。。不过这个对于实际应用中不会造成任何问题
as转换的性能缺陷
C#2.0中有了as转换操作符,在之前我们需要先is 是否是某类型然后再强制转换。而as一次就够了,但是令人惊讶的是它的性能竟然不如之前的解决方案,事实上是差很多,下次进行了测试两个版本
耗时分别是 1724 与 4919,不过我们敲码时如果整体性能不错,那么也可以使用as,毕竟优雅了很多。而且这也是一千万次的测试的结果
空合并操作符
对于可空类型的值类型,我们在判断时相比较值类型又多了一项判断那就是为null的判断。我们的代码看起来就是下面这样
If(i==null)
{
return 0;
}else
{
return I;
}
而空合并操作符??为我们提供了简便
Var x = i??0;
意思就是i为null吗?不为null就用i的值返回,为null就用后面的值返回,而且这样条件可以一直延续下去。空合并操作符还可以适用于引用类型
Var x= i??y??d??c??0;
我们还可以空合并操作符来简化我们的逻辑判断,重写比較器CompareTo,让其返回不是int而是int?。这样我们就可以使用??了