日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

【转】[你必须知道的.NET]第二十一回:认识全面的null

發布時間:2025/3/21 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】[你必须知道的.NET]第二十一回:认识全面的null 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

引用自:http://www.cnblogs.com/anytao/category/155694.html

作者: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????? : Anytaohttp://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
  • 引用isas模式對類型進行判斷或轉換時,需要做進一步的null判斷。

?

快捷參考

  • 關于isas模式,可以參考《你必須知道的.NET 7.5恩怨情仇:isas”
  • 第一回:恩怨情仇:isas

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? www.anytao.com

  • 判斷一個變量是否為null,可以應用==!=操作符來完成。
  • 對任何值為null變量操作,都會拋出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????? : Anytaohttp://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????? : Anytaohttp://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????? : Anytaohttp://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????? : Anytaohttp://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????? : Anytaohttp://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????? : Anytaohttp://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????? : Anytaohttp://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,仍然可以進行探討,我們將這種思考繼續,所收獲的果實就越多。

總結

以上是生活随笔為你收集整理的【转】[你必须知道的.NET]第二十一回:认识全面的null的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 三级免费毛片 | 自拍偷拍日韩 | 中文字幕在线免费 | 日韩久久高清 | 高清乱码免费网 | 无码精品国产一区二区三区免费 | 色悠悠国产精品 | 亚洲成av人片一区二区 | 亚洲中文字幕在线观看 | 91天天色 | 日日夜夜噜噜噜 | 国精产品一区一区三区视频 | 久草热在线 | 日韩福利社 | 亚洲码国产精品高潮在线 | 91高清视频免费观看 | 人人搞人人爱 | 亚洲人成电影网站 | 999免费| 成人三级黄色片 | 欧美深夜在线 | 人妻互换一区二区激情偷拍 | 调教撅屁股啪调教打臀缝av | 免费在线网站 | 欧美日韩一区在线观看 | 特大黑人巨交吊性xxxx视频 | 日本va在线观看 | 国产欧美一区二区三区白浆喷水 | 亚洲风情亚aⅴ在线发布 | 国产三级黄色 | 99免费在线视频 | 一区二区三区在线看 | 久久日韩| 欧美日韩一区二区三区在线播放 | 免费国产精品视频 | 久久爱综合网 | 欧产日产国产精品98 | 综合久久一区 | 国产av剧情一区 | 午夜伦理福利视频 | 国产在线观看你懂的 | 国产精品视频在线观看免费 | 久久精品人妻一区二区三区 | 亚洲综合图片网 | 亚洲av无码一区二区三区网址 | 精品人妻午夜一区二区三区四区 | 欧美日韩精品在线播放 | 97国产精品人人爽人人做 | 成人二三区| 久久精彩免费视频 | av网页在线 | 国产精品视频一区二区在线观看 | 淫片网站 | 久久先锋 | 涩色网站| 欧洲金发美女大战黑人 | 成人av图片 | 91成人看| 中文字幕人妻一区二区三区 | 免费aa视频 | 日韩精品视频免费看 | v99av | 久久人人爽人人爽人人片 | 日本三级影院 | 欧美三级成人 | 国产成人毛毛毛片 | 一级黄色片一级黄色片 | 在线免费看av网站 | 久久中文字幕在线观看 | 久久亚洲AV无码 | 亚洲永久精品一区二区 | 天天看片天天干 | 国产一页 | 欧美日韩综合一区 | 熟女少妇a性色生活片毛片 亚洲伊人成人网 | 午夜福利三级理论电影 | 先锋av资源在线 | 日本嫩草影院 | 狂野欧美性猛交xxxx巴西 | 亚洲特级黄色片 | 中文字幕日本一区二区 | 天天干天天爱天天操 | 9191国产精品 | 欧美剧场 | 婷婷毛片 | 蜜臀av无码一区二区三区 | 免费视频国产 | 国产欧美久久久精品免费 | 免费成人在线看 | 国产一级特黄 | 亚洲精品国产精品乱码不99按摩 | 浪漫樱花动漫在线观看免费 | 超黄网站在线观看 | av大片网址 | 日韩成人看片 | 北条麻妃av在线 | 国产一级一级 | 成人国产精品一区 | 华人色 |