亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

可空類(lèi)型Nullable<T>用法詳解

 更新時(shí)間:2022年02月21日 08:59:54   作者:Sweet-Tang  
本文詳細(xì)講解了可空類(lèi)型Nullable<T>的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、簡(jiǎn)介

眾所周知,值類(lèi)型變量不能null,這也是為什么它們被稱(chēng)為值類(lèi)型。但是,在實(shí)際的開(kāi)發(fā)過(guò)程中,也需要值為null的一些場(chǎng)景。例如以下場(chǎng)景:

場(chǎng)景1:您從數(shù)據(jù)庫(kù)表中檢索可空的整數(shù)數(shù)據(jù)列,數(shù)據(jù)庫(kù)中的null值沒(méi)有辦法將此值分配給C#中Int32類(lèi)型;

場(chǎng)景2:您在UI綁定屬性,但是某些值類(lèi)型的字段不是必須錄入的(例如在人員管理中的死亡日期);

場(chǎng)景3:在Java中,java.Util.Date是一個(gè)引用類(lèi)型,因此可以將此類(lèi)型的字段設(shè)置為null。但是,在CLR中,System.DateTime是一個(gè)值類(lèi)型,DateTime 變量不能null。如果使用Java編寫(xiě)的應(yīng)用程序要將日期/時(shí)間傳達(dá)給在CLR上運(yùn)行的Web服務(wù),如果Java應(yīng)用程序發(fā)送是null, CLR中沒(méi)有供對(duì)應(yīng)的類(lèi)型;

場(chǎng)景4:在函數(shù)中傳遞值類(lèi)型時(shí),如果參數(shù)的值無(wú)法提供并且不想傳遞,可以使用默認(rèn)值。但有時(shí)默認(rèn)值并不是最佳的選擇,因?yàn)槟J(rèn)值實(shí)際也傳遞了一個(gè)默認(rèn)的參數(shù)值,邏輯需要特殊的處理;

場(chǎng)景5:當(dāng)從xml或json反序列化數(shù)據(jù)時(shí),數(shù)據(jù)源中缺少某個(gè)值類(lèi)型屬性的值,這種情況很不方便處理。

當(dāng)然,我們?nèi)粘9ぷ髦羞€有很多類(lèi)似的情況。

為了擺脫這些情況,Microsoft在CLR中增加了可為空值類(lèi)型的概念。為了更清楚理解這一點(diǎn),我們看一下System.Nullable<T>類(lèi)型的邏輯定義:

 namespace System
 {
     [Serializable]
     public struct Nullable<T> where T : struct 
     {
         private bool hasValue;
         internal T value;
  
         public Nullable(T value) {
             this.value = value; 
             this.hasValue = true;
         }
 
         public bool HasValue { 
             get {
                 return hasValue; 
             } 
         }
  
         public T Value { 
             get {
                 if (!HasValue) { 
                     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); 
                 }
                 return value; 
             }
         }
 
         public T GetValueOrDefault() { 
             return value;
         } 
 
         public T GetValueOrDefault(T defaultValue) {
             return HasValue ? value : defaultValue;
         } 
 
         public override bool Equals(object other) { 
             if (!HasValue) return other == null; 
             if (other == null) return false;
             return value.Equals(other); 
         }
 
         public override int GetHashCode() {
             return HasValue ? value.GetHashCode() : 0; 
         }
  
         public override string ToString() { 
             return HasValue ? value.ToString() : "";
         } 
 
         public static implicit operator Nullable<T>(T value) {
             return new Nullable<T>(value);
         } 
 
         public static explicit operator T(Nullable<T> value) { 
             return value.Value; 
         }
     }
 }

從上面的定義可以總結(jié)如下幾點(diǎn):

  • Nullable<T> 類(lèi)型也是一個(gè)值類(lèi)型;
  • Nullable<T> 類(lèi)型包含一個(gè)Value屬性用于表示基礎(chǔ)值,還包括一個(gè)Boolean類(lèi)型的HasValue屬性用于表示該值是否為null ;
  • Nullable<T> 是一個(gè)輕量級(jí)的值類(lèi)型。Nullable<T>類(lèi)型的實(shí)例占用內(nèi)存的大小等于一個(gè)值類(lèi)型與一個(gè)Boolean類(lèi)型占用內(nèi)存大小之和;
  • Nullable<T> 的泛型參數(shù)T必須是值類(lèi)型。您只能將Nullable<T>類(lèi)型與值類(lèi)型結(jié)合使用,您也可以使用用戶定義的值類(lèi)型。

二、語(yǔ)法和用法

使用Nullable<T>類(lèi)型,只需指定一個(gè)其它值類(lèi)型的泛型參數(shù)T。

示例:

    Nullable<int> i = 1;
    Nullable<int> j = null;
    Nullable<Nullable<int>> k; //這是一個(gè)錯(cuò)誤語(yǔ)法,編譯會(huì)報(bào)錯(cuò)。

CLR還提供了一種簡(jiǎn)寫(xiě)的方式。

     int? i = 1;
     int? j = null;

可以通過(guò) Value 屬性來(lái)獲取基礎(chǔ)類(lèi)型的值。如下所示,如果不為null,則將返回實(shí)際的值,否則將拋出InvalidOperationException異常;您可以在調(diào)用Value屬性的時(shí),需要檢查是否為null。

     Nullable<int> i = 1;
     Nullable<int> j = null;
 
     Console.WriteLine(i.HasValue);
     //輸出結(jié)果:True
 
     Console.WriteLine(i.Value);
     //輸出結(jié)果:1
 
     Console.WriteLine(j.HasValue);
     //輸出結(jié)果:False
 
     Console.WriteLine(j.Value);
     //拋異常: System.InvalidOperationException

三、類(lèi)型的轉(zhuǎn)換和運(yùn)算

C#還支持簡(jiǎn)單的語(yǔ)法來(lái)使用Nullable<T>類(lèi)型。它還支持Nullable<T>實(shí)例的隱式轉(zhuǎn)換和轉(zhuǎn)換。如下示例演示:

     // 從System.Int32隱式轉(zhuǎn)換為Nullable<Int32> 
     int? i = 5;
 
     // 從'null'隱式轉(zhuǎn)換為Nullable<Int32> 
     int? j = null;
 
     // 從Nullable<Int32>到Int32的顯式轉(zhuǎn)換
     int k = (int)i;
 
     // 基礎(chǔ)類(lèi)型之間的轉(zhuǎn)換
     Double? x = 5; // 從Int到Nullable<Double> 的隱式轉(zhuǎn)換
     Double? y = j; // 從Nullable<Int32> 隱式轉(zhuǎn)換Nullable<Double>

對(duì)Nullable<T> 類(lèi)型使用操作符,與包含的基礎(chǔ)類(lèi)型使用方法相同。

  • 一元運(yùn)算符(++、--、 - 等),如果Nullable<T>類(lèi)型值是null時(shí),返回null;
  • 二元運(yùn)算符(+、-、*、/、%、^等)任何操作數(shù)是null,返回null;
  • 對(duì)于==運(yùn)算符,如果兩個(gè)操作數(shù)都是null,則表達(dá)式計(jì)算結(jié)果為true,如果任何一個(gè)操作數(shù)是null,則表達(dá)式計(jì)算結(jié)果為false;如果兩者都不為null,它照常比較。
  • 對(duì)于關(guān)系運(yùn)算符(>、<、>=、<=),如果任何一個(gè)操作數(shù)是null,則運(yùn)算結(jié)果是false,如果操作數(shù)都不為null,則比較該值。

見(jiàn)下面的例子:

     int? i = 5;
     int? j = null;
 
     // 一元運(yùn)算符
     i++; // i = 6 
     j = -j; // j = null
 
     // 二元運(yùn)算符
     i = i + 3; // i = 9 
     j = j * 3; // j = null;
 
     // 等號(hào)運(yùn)算符(==、!=)
     var r = i == null; //r = false
     r = j == null; //r = true
     r = i != j; //r = true
 
     // 比較運(yùn)算符(<、>、<=、>=)
     r = i > j; //r = false
 
     i = null;
     r = i >= j; //r = false,注意,i=null、j=null,但是>=返回的結(jié)果是false

Nullable<T>也可以像引用類(lèi)型一樣,支持三元操作符。

     // 如果雇員的年齡返回null(出生日期可能未輸入),請(qǐng)?jiān)O(shè)置值0. 
     int age = employee.Age ?? 0;
 
     // 在聚合函數(shù)中使用三元操作符。
     int?[] numbers = {};
     int total = numbers.Sum() ?? 0;

四、裝箱與拆箱

我們已經(jīng)知道了Nullable<T>是一個(gè)值類(lèi)型,現(xiàn)在我們?cè)賮?lái)聊一聊它的裝箱與拆箱。

CLR采用一個(gè)特殊的規(guī)則來(lái)處理Nullable<T>類(lèi)型的裝箱與拆箱。當(dāng)一個(gè)Nullable<T>類(lèi)型的實(shí)例裝箱時(shí),CLR會(huì)檢查實(shí)例的HasValue屬性:如果是true,則將實(shí)例Value屬性的值進(jìn)行裝箱后返回結(jié)果;如果返回false,則直接返回null,不做任何的處理。

在拆箱處理時(shí),與裝箱處反。CLR會(huì)檢查拆箱的對(duì)象是否為null,如果是直接創(chuàng)建一個(gè)新的實(shí)例 new Nullable<T>(),如果不為null,則將對(duì)象拆箱為類(lèi)型T,然后創(chuàng)建一個(gè)新實(shí)例 new Nullable<T>(t)。 

     int? n = null;
     object o = n; //不會(huì)進(jìn)行裝箱操作,直接返回null值
 
     Console.WriteLine("o is null = {0}", object.ReferenceEquals(o, null));
     //輸出結(jié)果:o is null = True
 
 
     n = 5;
     o = n; //o引用一個(gè)已裝箱的Int32
 
     Console.WriteLine("o's type = {0}", o.GetType());
     //輸出結(jié)果:o's type = System.Int32
 
     o = 5;
 
     //將Int32類(lèi)型拆箱為Nullable<Int32>類(lèi)型
     int? a = (Int32?)o; // a = 5 
     //將Int32類(lèi)型拆箱為Int32類(lèi)型
     int b = (Int32)o; // b = 5
 
     // 創(chuàng)建一個(gè)初始化為null
     o = null;
     // 將null變?yōu)镹ullable<Int32>類(lèi)型
     a = (Int32?)o; // a = null 
     b = (Int32)o; // 拋出異常:NullReferenceException

五、GetType()方法

當(dāng)調(diào)用Nullable<T>類(lèi)型的GetType()方法時(shí),CLR實(shí)際返回類(lèi)型的是泛型參數(shù)的類(lèi)型。因此,您可能無(wú)法區(qū)分Nullable<Int32>實(shí)例上是一個(gè)Int32類(lèi)型還是Nullable<Int32>。見(jiàn)下面的例子:

     int? i = 10;
     Console.WriteLine(i.GetType());
     //輸出結(jié)果是:System.Int32
     
     i = null;
     Console.WriteLine(i.GetType()); //NullReferenceException

原因分析:

這是因?yàn)檎{(diào)用GetType()方法時(shí),已經(jīng)將當(dāng)前實(shí)例進(jìn)行了裝箱,根據(jù)上一部分裝箱與拆箱的內(nèi)容,這里實(shí)際上調(diào)用的是Int32類(lèi)型的GetType()方法。

調(diào)用值類(lèi)型的GetType()方法時(shí),均會(huì)產(chǎn)生裝箱,關(guān)于這一點(diǎn)大家可以自己去驗(yàn)證。

六、ToString()方法

 當(dāng)調(diào)用Nullable<T>類(lèi)型的ToString()方法時(shí),如果HasValue屬性的值為false,則返回String.Empty,如果該屬性的值為true,則調(diào)用的邏輯是Value.ToString()。 見(jiàn)下面的例子:

     int? i = 10;
     Console.WriteLine(i.ToString());
     //輸出結(jié)果:10
 
     i = null;
     Console.WriteLine(i.ToString() == string.Empty);
     //輸出結(jié)果:True

七、System.Nullable幫助類(lèi)

 微軟還提供一個(gè)同名System.Nullable的靜態(tài)類(lèi),包括三個(gè)方法: 

 public static class Nullable
 {
     //返回指定的可空類(lèi)型的基礎(chǔ)類(lèi)型參數(shù)。
     public static Type GetUnderlyingType(Type nullableType);
 
     //比較兩個(gè)相對(duì)值 System.Nullable<T> 對(duì)象。
     public static int Compare<T>(T? n1, T? n2) where T : struct
 
     //指示兩個(gè)指定 System.Nullable<T> 對(duì)象是否相等。
     public static bool Equals<T>(T? n1, T? n2) where T : struct
 }

在這里面我們重點(diǎn)說(shuō)明一下GetUnderlyingType(Type nullableType)方法,另外兩個(gè)方法是用來(lái)比較值的,大家可以自己研究。

GetUnderlyingType(Type nullableType)方法是用來(lái)返回一個(gè)可為空類(lèi)型的基礎(chǔ)類(lèi)型,如果 nullableType 參數(shù)不是一個(gè)封閉的Nullable<T>泛型,則反回null。 

     Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable<int>)));
     //輸出結(jié)果:System.Int32
 
     Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable<>)) == null);
     //輸出結(jié)果:True
 
     Console.WriteLine(Nullable.GetUnderlyingType(typeof(int)) == null);
     //輸出結(jié)果:True
 
     Console.WriteLine(Nullable.GetUnderlyingType(typeof(string)) == null);
     //輸出結(jié)果:True

八、語(yǔ)法糖

微軟對(duì)Nullable<T>提供了豐富的語(yǔ)法糖來(lái)減少開(kāi)發(fā)員的工作量,下面是我想到供您參考。

簡(jiǎn)寫(xiě)

    int? i = 5;

    int? j = null;

    var r = i != null;

    var v = (int) i;

    i++;

    i = i + 3;

    r = i != j;

    r = i >= j;

    var k = i + j;

    double? x = 5;

    double? y = j;

編譯后的語(yǔ)句

    int? i = new int?(5);

    int? j = new int?();

    var r = i.HasValue;

    var v = i.Value;

    i = i.HasValue ? new int?(i.GetValueOrDefault() + 1) : new int?();

    i = i.HasValue ? new int?(i.GetValueOrDefault() + 3) : new int?();

    r = i.GetValueOrDefault() != j.GetValueOrDefault() || i.HasValue != j.HasValue;

    r = i.GetValueOrDefault() >= j.GetValueOrDefault() && i.HasValue & j.HasValue;

    int? k = i.HasValue & j.HasValue ? new int?(i.GetValueOrDefault() + j.GetValueOrDefault()) : new int?();

    double? x = new double?((double) 5);

    double? y = j.HasValue ? new double?((double) j.GetValueOrDefault()) : new double?();

到此這篇關(guān)于可空類(lèi)型Nullable<T>用法詳解的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#實(shí)現(xiàn)XML文件與DataTable、Dataset互轉(zhuǎn)

    C#實(shí)現(xiàn)XML文件與DataTable、Dataset互轉(zhuǎn)

    這篇文章介紹了C#實(shí)現(xiàn)XML文件與DataTable、Dataset互轉(zhuǎn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#中類(lèi)的使用教程詳解

    C#中類(lèi)的使用教程詳解

    在對(duì)類(lèi)訪問(wèn)使用時(shí),常用到的有訪問(wèn)類(lèi)的成員、方法。本文就將通過(guò)示例為大家詳細(xì)講講C#中類(lèi)的使用教程,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2022-07-07
  • C#的十種語(yǔ)法糖介紹

    C#的十種語(yǔ)法糖介紹

    這篇文章介紹了C#的十種語(yǔ)法糖,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 基于WPF實(shí)現(xiàn)簡(jiǎn)單放大鏡效果

    基于WPF實(shí)現(xiàn)簡(jiǎn)單放大鏡效果

    這篇文章主要為大家詳細(xì)介紹了WPF如何實(shí)現(xiàn)簡(jiǎn)單放大鏡效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • WPF實(shí)現(xiàn)Interaction框架的Behavior擴(kuò)展

    WPF實(shí)現(xiàn)Interaction框架的Behavior擴(kuò)展

    這篇文章介紹了WPF實(shí)現(xiàn)Interaction框架Behavior擴(kuò)展的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 深入了解C#設(shè)計(jì)模式之訂閱發(fā)布模式

    深入了解C#設(shè)計(jì)模式之訂閱發(fā)布模式

    這篇文章主要介紹了C#設(shè)計(jì)模式之訂閱發(fā)布模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作示例

    C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作示例

    這篇文章主要介紹了C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作,結(jié)合實(shí)例形式分析了C#針對(duì)base64編碼與圖片的相互轉(zhuǎn)換操作技巧,需要的朋友可以參考下
    2017-06-06
  • C#使用密封類(lèi)實(shí)現(xiàn)密封用戶信息的示例詳解

    C#使用密封類(lèi)實(shí)現(xiàn)密封用戶信息的示例詳解

    在C#中,密封類(lèi)(sealed class)是一種不能被其他類(lèi)繼承的類(lèi),它用于防止其他類(lèi)繼承它的功能和屬性, 下面我們就來(lái)看看如何使用密封類(lèi)密封用戶的信息吧
    2024-02-02
  • C#使用Aspose.Cells創(chuàng)建和讀取Excel文件

    C#使用Aspose.Cells創(chuàng)建和讀取Excel文件

    這篇文章主要為大家詳細(xì)介紹了C#使用Aspose.Cells創(chuàng)建和讀取Excel文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • C#操作注冊(cè)表之RegistryKey類(lèi)

    C#操作注冊(cè)表之RegistryKey類(lèi)

    這篇文章介紹了C#操作注冊(cè)表之RegistryKey類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05

最新評(píng)論