Welcome

首页 / 软件开发 / .NET编程技术 / [你必须知道的.NET]第二十一回:认识全面的null

[你必须知道的.NET]第二十一回:认识全面的null2011-03-23 博客园 Anytao1 从什么是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则将空引用保存。