[你必須知道的.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異常。