<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

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

      《你必須知道的.NET》網站 | Anytao技術博客 

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

      發布日期:2008.7.31 作者:Anytao
      ? 2008 Anytao.com ,Anytao原創作品,轉貼請注明作者和出處。

      說在,開篇之前

      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異常。

       

      2 Nullable<T>(可空類型)

       

      一直以來,null都是引用類型的特有產物,對值類型進行null操作將在編譯器拋出錯誤提示,例如:

                  //拋出編譯時錯誤
                  int i = null;  
                  if (i == null)
                  {
                      Console.WriteLine("i is null.");
                  }

      正如示例中所示,很多情況下作為開發人員,我們更希望能夠以統一的方式來處理,同時也希望能夠解決實際業務需求中對于“值”也可以為“空”這一實際情況的映射。因此,自.NET 2.0以來,這一特權被新的System.Nullable<T>(即,可空值類型)的誕生而打破,解除上述詬病可以很容易以下面的方式被實現:

                  //Nullable<T>解決了這一問題
                  int? i = null;
                  if (i == null)
                  {
                      Console.WriteLine("i is null.");
                  }

      你可能很奇怪上述示例中并沒有任何Nullable的影子,實際上這是C#的一個語法糖,以下代碼在本質上是完全等效的:

                  int? i = null;
                  Nullable<int> i = null;

      顯然,我們更中意以第一種簡潔而優雅的方式來實現我們的代碼,但是在本質上Nullable<T>T?他們是一路貨色。

      可空類型的偉大意義在于,通過Nullable<T>類型,.NET為值類型添加“可空性”,例如Nullable<Boolean>的值就包括了true、false和null,而Nullable<Int32>則表示值即可以為整形也可以為null。同時,可空類型實現了統一的方式來處理值類型和引用類型的“空”值問題,例如值類型也可以享有在運行時以NullReferenceException異常來處理。

      另外,可空類型是內置于CLR的,所以它并非c#的獨門絕技,VB.NET中同樣存在相同的概念。

      Nullable的本質(IL)

      那么我們如何來認識Nullable的本質呢?當你聲明一個:

                  Nullable<Int32> count = new Nullable<Int32>();

      時,到底發生了什么樣的過程呢?我們首先來了解一下Nullable在.NET中的定義:

          public struct Nullable<T> where T : struct
          {
              private bool hasValue;
              internal T value;
              public Nullable(T value);
              public bool HasValue { get; }
              public T Value { get; }
              public T GetValueOrDefault();
              public T GetValueOrDefault(T defaultValue);
              public override bool Equals(object other);
              public override int GetHashCode();
              public override string ToString();
              public static implicit operator T?(T value);
              public static explicit operator T(T? value);
          }

      根據上述定義可知,Nullable本質上仍是一個struct為值類型,其實例對象仍然分配在線程棧上。其中的value屬性封裝了具體的值類型,Nullable<T>進行初始化時,將值類型賦給value,可以從其構造函數獲知:

              public Nullable(T value)
              {
                  this.value = value;
                  this.hasValue = true;
              }

      同時Nullable<T>實現相應的Equals、ToString、GetHashCode方法,以及顯式和隱式對原始值類型與可空類型的轉換。因此,在本質上Nullable可以看著是預定義的struct類型,創建一個Nullable<T>類型的IL表示可以非常清晰的提供例證,例如創建一個值為int型可空類型過程,其IL可以表示為:

          .method private hidebysig static void Main() cil managed
          {
              .entrypoint
              .maxstack 2
              .locals init (
                  [0] valuetype [mscorlib]System.Nullable`1<int32> a)
              L_0000: nop 
              L_0001: ldloca.s a
              L_0003: ldc.i4 0x3e8
              L_0008: call instance void [mscorlib]System.Nullable`1<int32>::.ctor(!0)
              L_000d: nop 
              L_000e: ret 
          }

      對于可空類型,同樣需要必要的小結:

      • 可空類型表示值為null的值類型。
      • 不允許使用嵌套的可空類型,例如Nullable<Nullable<T>> 。
      • Nullable<T>和T?是等效的。
      • 對可空類型執行GetType方法,將返回類型T,而不是Nullable<T>。
      • c#允許在可空類型上執行轉換和轉型,例如:
                  int? a = 100;
                  Int32 b = (Int32)a;
                  a = null;
      • 同時為了更好的將可空類型于原有的類型系統進行兼容,CLR提供了對可空類型裝箱和拆箱的支持。

       

       

      3 ??運算符

      在實際的程序開發中,為了有效避免發生異常情況,進行null判定是經常發生的事情,例如對于任意對象執行ToString()操作,都應該進行必要的null檢查,以免發生不必要的異常提示,我們常常是這樣實現的:

                  object obj = new object();
       
                  string objName = string.Empty;
                  if (obj != null)
                  {
                      objName = obj.ToString();
                  }
       
                  Console.WriteLine(objName);

      然而這種實現實在是令人作嘔,滿篇的if語句總是讓人看著渾身不適,那么還有更好的實現方式嗎,我們可以嘗試(? :)三元運算符:

                  object obj = new object();
                  string objName = obj == null ? string.Empty : obj.ToString();
                  Console.WriteLine(objName);

      上述obj可以代表任意的自定義類型對象,你可以通過覆寫ToString方法來輸出你想要輸出的結果,因為上述實現是如此的頻繁,所以.NET 3.0中提供了新的操作運算符來簡化null值的判斷過程,這就是:??運算符。上述過程可以以更加震撼的代碼表現為:

                  // Copyright   : www.anytao.com        
                  // Author      : Anytao,http://www.anytao.com        
                  // Release     : 2008/07/31 1.0
       
                  object obj = null;
                  string objName = (obj ?? string.Empty).ToString();
                  Console.WriteLine(objName);

      那么??運算符的具體作用是什么呢?

      ??運算符,又稱為null-coalescing operator,如果左側操作數為null,則返回右側操作數的值, 如果不為null則返回左側操作數的值。它既可以應用于可空類型,有可以應用于引用類型。

      插播廣告,我的新書

       

      4 Nulll Object模式

      模式之于設計,正如秘笈之于功夫。正如我們前文所述,null在程序設計中具有舉足輕重的作用,因此如何更優雅的處理“對象為空”這一普遍問題,大師們提出了Null Object Pattern概念,也就是我們常說的Null Object模式。例如Bob大叔在《敏捷軟件開發--原則、模式、實踐》一書,Martin Fowler在《Refactoring: Improving the Design of Existing Code》一書,都曾就Null Object模式展開詳細的討論,可見23中模式之外還是有很多設計精髓,可能稱為模式有礙經典。但是仍然值得我們挖據、探索和發現。
      下面就趁熱打鐵,在null認識的基礎上,對null object模式進行一點探討,研究null object解決的問題,并提出通用的null object應用方式。
      解決什么問題?
      簡單來說,null object模式就是為對象提供一個指定的類型,來代替對象為空的情況。說白了就是解決對象為空的情況,提供對象“什么也不做”的行為,這種方式看似無聊,但卻是很聰明的解決之道。舉例來說,一個User類型對象user需要在系統中進行操作,那么典型的操作方式是:

                  if (user != null)
                  {
                      manager.SendMessage(user);
                  }

      這種類似的操作,會遍布于你的系統代碼,無數的if判斷讓優雅遠離了你的代碼,如果大意忘記null判斷,那么只有無情的異常伺候了。于是,Null object模式就應運而生了,對User類實現相同功能的NullUser類型,就可以有效的避免繁瑣的if和不必要的失誤:

          // Copyright   : www.anytao.com        
          // Author      : Anytao,http://www.anytao.com        
          // Release     : 2008/07/31 1.0
       
          public class NullUser : IUser
          {
              public void Login()
              {
                  //不做任何處理
              }
       
              public void GetInfo() { }
       
              public bool IsNull
              {
                  get { return true; }
              }
          }

      IsNull屬性用于提供統一判定null方式,如果對象為NullUser實例,那么IsNull一定是true的。

      那么,二者的差別體現在哪兒呢?其實主要的思路就是將null value轉換為null object,把對user == null這樣的判斷,轉換為user.IsNull雖然只有一字之差,但是本質上是完全兩回事兒。通過null object模式,可以確保返回有效的對象,而不是沒有任何意義的null值。同時,“在執行方法時返回null object而不是null值,可以避免NullReferenceExecption異常的發生。”,這是來自Scott Dorman的聲音。

      通用的null object方案

      下面,我們實現一種較為通用的null object模式方案,并將其實現為具有.NET特色的null object,所以我們采取實現.NET中INullable接口的方式來實現,INullable接口是一個包括了IsNull屬性的接口,其定義為:

          public interface INullable
          {
              // Properties
              bool IsNull { get; }
          }

      仍然以User類為例,實現的方案可以表達為:

      圖中僅僅列舉了簡單的幾個方法或屬性,旨在達到說明思路的目的,其中User的定義為:

          // Copyright   : www.anytao.com        
          // Author      : Anytao,http://www.anytao.com        
          // Release     : 2008/07/31 1.0
       
          public class User : IUser
          {
              public void Login()
              {
                  Console.WriteLine("User Login now.");
              }
       
              public void GetInfo()
              {
                  Console.WriteLine("User Logout now.");
              }
       
              public bool IsNull
              {
                  get { return false; }
              }
          }

      而對應的NullUser,其定義為:

          // Copyright   : www.anytao.com        
          // Author      : Anytao,http://www.anytao.com        
          // Release     : 2008/07/31 1.0
       
          public class NullUser : IUser
          {
              public void Login()
              {
                  //不做任何處理
              }
       
              public void GetInfo() { }
       
              public bool IsNull
              {
                  get { return true; }
              }
          }

      同時通過UserManager類來完成對User的操作和管理,你很容易思考通過關聯方式,將IUser作為UserManger的屬性來實現,基于對null object的引入,實現的方式可以為:

          // Copyright   : www.anytao.com        
          // Author      : Anytao,http://www.anytao.com        
          // Release     : 2008/07/31 1.0
       
          class UserManager
          {
              private IUser user = new User();
       
              public IUser User
              {
                  get { return user; }
                  set
                  {
                      user = value ?? new NullUser();
                  }
              }
          }

      當然有效的測試是必要的:

              public static void Main()
              {
                  UserManager manager = new UserManager();
                  //強制為null
                  manager.User = null;
                  //執行正常
                  manager.User.Login();
       
                  if (manager.User.IsNull)
                  {
                      Console.WriteLine("用戶不存在,請檢查。");
                  }
              }

      通過強制將User屬性實現為null,在調用Login時仍然能夠保證系統的穩定性,有效避免對null的判定操作,這至少可以讓我們的系統少了很多不必要的判定代碼。

      詳細的代碼可以通過本文最后的下載空間進行下載。實際上,可以通過引入Facotry Method模式來構建對于User和NullUser的創建工作,這樣就可以完全消除應用if進行判斷的僵化,不過那是另外一項工作罷了。

      當然,這只是null object的一種實現方案,在此對《Refactoring》一書的示例進行改良,完成更具有.NET特色的null object實現,你也可以請NullUser繼承Use并添加相應的IsNull判定屬性來完成。

      借力c# 3.0的Null object

      在C# 3.0中,Extension Method(擴展方法)對于成就LINQ居功至偉,但是Extension Method的神奇遠不是止于LINQ。在實際的設計中,靈活而巧妙的應用,同樣可以給你的設計帶來意想不到的震撼,以上述User為例我們應用Extension Method來取巧實現更簡潔IsNull判定,代替實現INullable接口的方法而采用更簡單的實現方式。重新構造一個實現相同功能的擴展方法,例如:

          // Copyright   : www.anytao.com        
          // Author      : Anytao,http://www.anytao.com        
          // Release     : 2008/07/31 1.0
       
          public static class UserExtension
          {
              public static bool IsNull(this User user)
              {
                  return null == user;
              }
          }
      當然,這只是一個簡單的思路,僅僅將對null value的判斷轉換為null object的判斷角度來看,擴展方法帶來了更有效的、更簡潔的表現力。 

      null object模式的小結

      • 有效解決對象為空的情況,為值為null提供可靠保證。
      • 保證能夠返回有效的默認值,例如在一個IList<User> userList中,能夠保證任何情況下都有有效值返回,可以保證對userList操作的有效性,例如:
              // Copyright   : www.anytao.com        
              // Author      : Anytao,http://www.anytao.com        
              // Release     : 2008/07/31 1.0
       
              public void SendMessageAll(List<User> userList)
              {
                  //不需要對userList進行null判斷
                  foreach (User user in userList)
                  {
                      user.SendMessage(); 
                  }
              }
      • 提供統一判定的IsNull屬性。可以通過實現INullable接口,也可以通過Extension Method實現IsNull判定方法。
      • null object要保持原object的所有成員的不變性,所以我們常常將其實現為Sigleton模式。
      • Scott Doman說“在執行方法時返回null object而不是null值,可以避免NullReferenceExecption異常的發生”,這完全是對的。

      5 結論

      雖然形色匆匆,但是通過本文你可以基本了解關于null這個話題的方方面面,堆積到一起就是對一個概念清晰的把握和探討。技術的魅力,大概也正是如此而已吧,色彩斑斕的世界里,即便是“什么都沒有”的null,在我看來依然有很多很多。。。值得探索、思考和分享。

      還有更多的null,例如LINQ中的null,SQL中的null,仍然可以進行探討,我們將這種思考繼續,所收獲的果實就越多。

      Anytao | 2008-07-31 | 你必須知道的.NET

      http://www.anytao.com/  | Blog: http://anytao.cnblogs.com/ | Anytao創作品,轉貼請注明作者和出處,留此信息。

       

      參考文獻

       

      (Book)Martin Fowler,Refactoring: Improving the Design of Existing Code

      (cnblogs)zhuweisky使用Null Object設計模式

      (blogs)Scott DormanNull Object pattern

       

       

      溫故知新

      [開篇有益]
      [第一回:恩怨情仇:is和as]
      [第二回:對抽象編程:接口和抽象類]
      [第三回:歷史糾葛:特性和屬性]
      [第四回:后來居上:class和struct]
      [第五回:深入淺出關鍵字---把new說透]
      [第六回:深入淺出關鍵字---base和this]
      [第七回:品味類型---從通用類型系統開始]
      [第八回:品味類型---值類型與引用類型(上)-內存有理]
      [第九回:品味類型---值類型與引用類型(中)-規則無邊]
      [第十回:品味類型---值類型與引用類型(下)-應用征途]
      [第十一回:參數之惑---傳遞的藝術(上)]
      [第十二回:參數之惑---傳遞的藝術(下)]
      [第十三回:從Hello, world開始認識IL]
      [第十四回:認識IL代碼---從開始到現在]
      [第十五回:繼承本質論]
      [第十六回:深入淺出關鍵字---using全接觸]
      [第十七回:貌合神離:覆寫和重載]
      [第十八回:對象創建始末(上)]
      [第十九回:對象創建始末(下)]
      [第二十回:學習方法論]

       

      ? 2008 Anytao.com 原創作品,轉貼請注明作者和出處,留此信息。

      本文以“現狀”提供且沒有任何擔保,同時也沒有授予任何權利。
      This posting is provided "AS IS" with no warranties, and confers no rights.

      posted @ 2008-07-31 01:13  Anytao  閱讀(16054)  評論(98)    收藏  舉報
      主站蜘蛛池模板: 中国CHINA体内裑精亚洲日本| 亚洲精品成人久久av| 丰满人妻熟妇乱精品视频| 亚洲精品色一区二区三区| 97se亚洲综合自在线| 精品国产一区二区三区av性色 | 蜜芽久久人人超碰爱香蕉| 人人人澡人人肉久久精品| 国产精品天干天干综合网| 老司机精品成人无码av| 黄色舔女人逼一区二区三区| 精品无码成人片一区二区98| 青草热在线观看精品视频| 吉首市| 日本熟妇人妻一区二区三区| 人妻少妇无码精品专区| 中文字幕日韩人妻一区| 午夜福利影院不卡影院| 国产乱码精品一区二三区| 日韩亚洲中文图片小说| 亚洲成av人片天堂网无码| 亚洲中文字幕一二三四区| 黑人巨大精品欧美一区二区| 东京道一本热中文字幕| 国产尤物精品自在拍视频首页| 长寿区| 欧洲无码一区二区三区在线观看| 国产精品一区二区三区四区| 日本一区二区三区专线| 亚洲一区三区三区成人久| 99精品高清在线播放| 亚洲欧美在线一区中文字幕| 亚洲av成人一区二区| 人人入人人爱| 欧美一区二区三区欧美日韩亚洲 | 伊人无码精品久久一区二区| 人妻夜夜爽天天爽三区麻豆av | 一区二区三区av天堂| 国内少妇人妻偷人精品视频| 悠悠人体艺术视频在线播放| 久久久久无码国产精品一区|