Nullable 解析

今天跟个朋友讨论了下Nullable

在此列入笔记稍作记录。

 

.net 3.0之后便引入了 值类型?的写法,例如 int?,float?等,其表示为可为空的值类型。

 

对于任何一个值类型的可空类型,其实现都是来自于 Nullable<T> 这个泛型的实现,而Nullable事实上是一个Struct

 

所以有时有人会有疑问,如果int?只是一个Struct的实现。那为什么以下代码能够编译通过:

Int? i = null;

因为对于Struct,它是一个值类型,是不能为它赋予null值的。

这是需要解析的第一点,比如我们上面的那句。

事实上,编译器在编译的时候,并不会把null赋予这个值类型。

它只是在调用了Nullable的一个默认初始化函数。我们可以从编译后的IL中看出。

而对于下面这样的代码:

Int? i = 5;

编译器做的也是像上面一样的事情,在这里他是调用了相应泛型T的构造函数,初始化了一个Nullable<T>的实例出来。

 

然后再根据IL来观察对一个可空值类型的重复赋值:

Int? i = 0;

int? n = null;

i = 2;

n = 3;

以上代码在编译时的表现是,每一次进行赋值,它都会初始化一个新的Nullable<int>的新实例出来。

 

 

 

嗯,现在从IL中我们已经可以看出,每次对可空类型的赋值,无论是赋初值还是重复赋值,

事实上都是实例化出了一个Nullable<T>泛型的结构体。

 

 

 

然后还是回到最初的那个问题,既然可空值类型是一个Struct,那它怎么可以跟null进行比较呢?

先看IL

 

 

 

从上面的IL来看,以上的语法全都是语法糖,为了方便开发人员写代码而制造出来的。因为当你书写以下的代码时:

Int? i = 0;

bool result = i == null;

比较调用的的并不是值类型的Equal,或者是引用类型的RefrenceEqual,

而是调用了Nullableget_HasValue方法,Nullable封装了该方法以检查该值是否已存在。

 

所以事实上这些都是编译器的魔法,他让开发人员书写少了很多繁琐的代码,但如果我们不深入去探讨,就会陷入一些迷惑,甚至忘记了代码的本质。

 

 

 

转载于:https://www.cnblogs.com/SinSay/archive/2010/09/23/1833227.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值