[你必须知道的.NET]第二十一回:认识全面的null
[2] [你必须知道的.NET]第二十一回:认识全面的null
[3] [你必须知道的.NET]第二十一回:认识全面的null
[4] [你必须知道的.NET]第二十一回:认识全面的null
[5] [你必须知道的.NET]第二十一回:认识全面的null
系列文章导航:
[你必须知道的.NET] 第四回:后来居上:class和struct
[你必须知道的.NET] 第五回:深入浅出关键字---把new说透
[你必须知道的.NET] 第六回:深入浅出关键字---base和this
[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始
[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理
[你必须知道的.NET] 第九回:品味类型---值类型与引用类型(中)-规则无边
[你必须知道的.NET] 第十回:品味类型---值类型与引用类型(下)-应用征途
[你必须知道的.NET] 第十一回:参数之惑---传递的艺术(上)
[你必须知道的.NET] 第十二回:参数之惑---传递的艺术(下)
[你必须知道的.NET] 第十三回:从Hello, world开始认识IL
[你必须知道的.NET] 第十四回:认识IL代码---从开始到现在
[你必须知道的.NET] 第十六回:深入浅出关键字---using全接触
[你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考
[你必须知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二
[你必须知道的.NET]第二十一回:认识全面的null
说在,开篇之前 |
null、nullable、??运算符、null object模式,这些闪亮的概念在你眼前晃动,我们有理由相信“存在即合理”,事实上,null不光合理,而且重要。本文,从null的基本认知开始,逐层了解可空类型、??运算符和null object模式,在循序之旅中了解不一样的null。 你必须知道的.NET,继续全新体验,分享更多色彩。 |
1 从什么是null开始?
null,一个值得尊敬的数据标识。
一般说来,null表示空类型,也就是表示什么都没有,但是“什么都没有”并不意味“什么都不是”。实际上,null是如此的重要,以致于在JavaScript中,Null类型就作为5种基本的原始类型之一,与Undefined、Boolean、Number和String并驾齐驱。这种重要性同样表现在.NET中,但是一定要澄清的是,null并不等同于0,"",string.Empty这些通常意义上的“零”值概念。相反,null具有实实在在的意义,这个意义就是用于标识变量引用的一种状态,这种状态表示没有引用任何对象实例,也就是表示“什么都没有”,既不是Object实例,也不是User实例,而是一个空引用而已。
在上述让我都拗口抓狂的表述中,其实中心思想就是澄清一个关于null意义的无力诉说,而在.NET中null又有什么实际的意义呢?
在.NET中,null表示一个对象引用是无效的。作为引用类型变量的默认值,null是针对指针(引用)而言的,它是引用类型变量的专属概念,表示一个引用类型变量声明但未初始化的状态,例如:
object obj = null;
此时obj仅仅是一个保存在线程栈上的引用指针,不代表任何意义,obj未指向任何有效实例,而被默认初始化为null。
object obj和object obj = null的区别?
那么,object obj和object obj = null有实际的区别吗?答案是:有。主要体现在编译器的检查上。默认情况下,创建一个引用类型变量时,CLR即将其初始化为null,表示不指向任何有效实例,所以本质上二者表示了相同的意义,但是有有所区别:
// Copyright : www.anytao.com
// Author : Anytao,http://www.anytao.com
// Release : 2008/07/31 1.0
//编译器检测错误:使用未赋值变量obj
//object obj;
//编译器理解为执行了初始化操作,所以不引发编译时错误
object obj = null;
if (obj == null)
{
//运行时抛出NullReferenceException异常
Console.WriteLine(obj.ToString());
}
注:当我把这个问题抛给几个朋友时,对此的想法都未形成统一的共识,几位同志各有各的理解,也各有个的道理。当然,我也慎重的对此进行了一番探讨和分析,但是并未形成完全100%确定性的答案。不过,在理解上我更倾向于自己的分析和判断,所以在给出上述结论的基础上,也将这个小小的思考留给大家来探讨,好的思考和分析别忘了留给大家。事实上,将
static void Main(string[] args)
{
object o;
object obj = null;
}
反编译为IL时,二者在IL层还是存在一定的差别:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] object o,
[1] object obj)
L_0000: nop
L_0001: ldnull
L_0002: stloc.1
L_0003: ret
}
前者没有发生任何附加操作;而后者通过ldnull指令推进一个空引用给evaluation stack,而stloc则将空引用保存。
回到规则
在.NET中,对null有如下的基本规则和应用:
- null为引用类型变量的默认值,为引用类型的概念范畴。
- null不等同于0,"",string.Empty。
- 引用is或as模式对类型进行判断或转换时,需要做进一步的null判断。
快捷参考 |
|
- 判断一个变量是否为null,可以应用==或!=操作符来完成。
- 对任何值为nul的l变量操作,都会抛出NullReferenceException异常。