[你必須知道的.NET]第二十一回:認識全面的null

作者: Anytao  來源: 博客園  發布時間: 2008-10-13 11:05  閱讀: 5528 次  推薦: 0   原文鏈接   [收藏]  
 

系列文章導航:

[你必須知道的.NET] 開篇有益

[你必須知道的.NET] 第一回:恩怨情仇:is和as

[你必須知道的.NET] 第二回:對抽象編程:接口和抽象類

[你必須知道的.NET] 第三回:歷史糾葛:特性和屬性

[你必須知道的.NET] 第四回:后來居上:class和struct

[你必須知道的.NET] 第五回:深入淺出關鍵字---把new說透

[你必須知道的.NET] 第六回:深入淺出關鍵字---base和this

[你必須知道的.NET] 第七回:品味類型---從通用類型系統開始

[你必須知道的.NET] 第八回:品味類型---值類型與引用類型(上)-內存有理

[你必須知道的.NET] 第九回:品味類型---值類型與引用類型(中)-規則無邊

[你必須知道的.NET] 第十回:品味類型---值類型與引用類型(下)-應用征途

[你必須知道的.NET] 第十一回:參數之惑---傳遞的藝術(上)

[你必須知道的.NET] 第十二回:參數之惑---傳遞的藝術(下)

[你必須知道的.NET] 第十三回:從Hello, world開始認識IL

[你必須知道的.NET] 第十四回:認識IL代碼---從開始到現在

[你必須知道的.NET] 第十五回:繼承本質論

[你必須知道的.NET] 第十六回:深入淺出關鍵字---using全接觸

[你必須知道的.NET] 第十七回:貌合神離:覆寫和重載

[你必須知道的.NET] 第十八回:對象創建始末(上)

[你必須知道的.NET] 第十九回:對象創建始末(下)

[你必須知道的.NET]第二十回:學習方法論

[你必須知道的.NET]第二十一回:認識全面的null

[你必須知道的.NET]第二十二回:字符串駐留(上)---帶著問題思考

[你必須知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二

 

[你必須知道的.NET]第二十一回:認識全面的null

說在,開篇之前

null、nullable、??運算符、null object模式,這些閃亮的概念在你眼前晃動,我們有理由相信“存在即合理”,事實上,null不光合理,而且重要。本文,從null的基本認知開始,逐層了解可空類型、??運算符和null object模式,在循序之旅中了解不一樣的null。

你必須知道的.NET,繼續全新體驗,分享更多色彩。

                                                                                                                       www.anytao.com

 

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判斷。

 

快捷參考

                                                                                                                       www.anytao.com

  • 判斷一個變量是否為null,可以應用==或!=操作符來完成。
  • 對任何值為nul的l變量操作,都會拋出NullReferenceException異常。

 

0
0
 
標簽:.NET null
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()