細說Nullable類型
目錄
一、簡介
二、語法和用法
三、類型的轉換和運算
四、裝箱與拆箱
五、GetType方法
六、ToString方法
七、System.Nullable幫助類
八、語法糖
一、簡介
眾所周知,值類型變數不能null,這也是為什麼它們被稱為值類型。但是,在實際的開發過程中,也需要值為null
的一些場景。例如以下場景:
場景1:您從資料庫表中檢索可空的整數數據列,資料庫中的null
值沒有辦法將此值分配給C#中Int32類型;
場景2:您在UI綁定屬性,但是某些值類型的欄位不是必須錄入的(例如在人員管理中的死亡日期);
場景3:在Java中,java.Util.Date
是一個引用類型,因此可以將此類型的欄位設置為null
。但是,在CLR中,System.DateTime
是一個值類型,DateTime 變數不能null
。如果使用Java編寫的應用程序要將日期/時間傳達給在CLR上運行的Web服務,如果Java應用程序發送是null
, CLR中沒有供對應的類型;
場景4:在函數中傳遞值類型時,如果參數的值無法提供並且不想傳遞,可以使用默認值。但有時默認值並不是最佳的選擇,因為默認值實際也傳遞了一個默認的參數值,邏輯需要特殊的處理;
場景5:當從xml或json反序列化數據時,數據源中缺少某個值類型屬性的值,這種情況很不方便處理。
當然,我們日常工作中還有很多類似的情況。
為了擺脫這些情況,Microsoft在CLR中增加了可為空值類型的概念。為了更清楚理解這一點,我們看一下System.Nullable
類型的邏輯定義:
1 namespace System 查看Nullable的定義 從上面的定義可以總結如下幾點: 二、語法和用法 使用Nullable 示例:
2 {
3 [Serializable]
4 public struct Nullable
5 {
6 private bool hasValue;
7 internal T value;
8
9 public Nullable(T value) {
10 this.value = value;
11 this.hasValue = true;
12 }
13
14 public bool HasValue {
15 get {
16 return hasValue;
17 }
18 }
19
20 public T Value {
21 get {
22 if (!HasValue) {
23 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
24 }
25 return value;
26 }
27 }
28
29 public T GetValueOrDefault {
30 return value;
31 }
32
33 public T GetValueOrDefault(T defaultValue) {
34 return HasValue ? value : defaultValue;
35 }
36
37 public override bool Equals(object other) {
38 if (!HasValue) return other == null;
39 if (other == null) return false;
40 return value.Equals(other);
41 }
42
43 public override int GetHashCode {
44 return HasValue ? value.GetHashCode : 0;
45 }
46
47 public override string ToString {
48 return HasValue ? value.ToString : "";
49 }
50
51 public static implicit operator Nullable
52 return new Nullable
53 }
54
55 public static explicit operator T(Nullable
56 return value.Value;
57 }
58 }
59 }
Boolean
類型的HasValue屬性用於表示該值是否為null
;Boolean
類型佔用內存大小之和;
1 Nullable CLR還提供了一種簡寫的方式。 1 int? i = 1; 可以通過 Value 屬性來獲取基礎類型的值。如下所示,如果不為 1 Nullable 三、類型的轉換和運算 C#還支持簡單的語法來使用Nullable 1 // 從System.Int32隱式轉換為Nullable 對Nullable 見下面的例子: 1 int? i = 5; Nullable 1 // 如果僱員的年齡返回null(出生日期可能未輸入),請設置值0. 四、裝箱與拆箱 我們已經知道了Nullable CLR採用一個特殊的規則來處理Nullable 在拆箱處理時,與裝箱處反。CLR會檢查拆箱的對象是否為 1 int? n = null; 五、GetType方法 當調用Nullable 1 int? i = 10; 原因分析: 這是因為調用 調用值類型的 當調用Nullable 1 int? i = 10; 七、System.Nullable幫助類 微軟還提供一個同名 1 public static class Nullable 在這裡面我們重點說明一下 1 Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable 八、語法糖 微軟對Nullable 參考:
2 Nullable
3 Nullable
2 int? j = null;
null
,則將返回實際的值,否則將拋出InvalidOperationException
異常;您可以在調用Value屬性的時,需要檢查是否為null
。
2 Nullable
3
4 Console.WriteLine(i.HasValue);
5 //輸出結果:True
6
7 Console.WriteLine(i.Value);
8 //輸出結果:1
9
10 Console.WriteLine(j.HasValue);
11 //輸出結果:False
12
13 Console.WriteLine(j.Value);
14 //拋異常: System.InvalidOperationException
2 int? i = 5;
3
4 // 從"null"隱式轉換為Nullable
5 int? j = null;
6
7 // 從Nullable
8 int k = (int)i;
9
10 // 基礎類型之間的轉換
11 Double? x = 5; // 從Int到Nullable
12 Double? y = j; // 從Nullable
null
時,返回null
;null
,返回null
;null
,則表達式計算結果為true
,如果任何一個操作數是null
,則表達式計算結果為false;如果兩者都不為null
,它照常比較。null
,則運算結果是false
,如果操作數都不為null
,則比較該值。
2 int? j = null;
3
4 // 一元運算符
5 i++; // i = 6
6 j = -j; // j = null
7
8 // 二元運算符
9 i = i + 3; // i = 9
10 j = j * 3; // j = null;
11
12 // 等號運算符(==、!=)
13 var r = i == null; //r = false
14 r = j == null; //r = true
15 r = i != j; //r = true
16
17 // 比較運算符(<、>、<=、>=)
18 r = i > j; //r = false
19
20 i = null;
21 r = i >= j; //r = false,注意,i=null、j=null,但是>=返回的結果是false
2 int age = employee.Age ?? 0;
3
4 // 在聚合函數中使用三元操作符。
5 int? numbers = {};
6 int total = numbers.Sum ?? 0;
true
,則將實例Value屬性的值進行裝箱後返回結果;如果返回false
,則直接返回null
,不做任何的處理。null
,如果是直接創建一個新的實例 new Nullablenull
,則將對象拆箱為類型T,然後創建一個新實例 new Nullable
2 object o = n; //不會進行裝箱操作,直接返回null值
3
4 Console.WriteLine("o is null = {0}", object.ReferenceEquals(o, null));
5 //輸出結果:o is null = True
6
7
8 n = 5;
9 o = n; //o引用一個已裝箱的Int32
10
11 Console.WriteLine("o"s type = {0}", o.GetType);
12 //輸出結果:o"s type = System.Int32
13
14 o = 5;
15
16 //將Int32類型拆箱為Nullable
17 int? a = (Int32?)o; // a = 5
18 //將Int32類型拆箱為Int32類型
19 int b = (Int32)o; // b = 5
20
21 // 創建一個初始化為null
22 o = null;
23 // 將null變為Nullable
24 a = (Int32?)o; // a = null
25 b = (Int32)o; // 拋出異常:NullReferenceException
GetType
方法時,CLR實際返回類型的是泛型參數的類型。因此,您可能無法區分Nullable
2 Console.WriteLine(i.GetType);
3 //輸出結果是:System.Int32
4
5 i = null;
6 Console.WriteLine(i.GetType); //NullReferenceException
GetType
方法時,已經將當前實例進行了裝箱,根據上一部分裝箱與拆箱的內容,這裡實際上調用的是Int32類型的GetType
方法。GetType
方法時,均會產生裝箱,關於這一點大家可以自己去驗證。ToString
方法時,如果HasValue屬性的值為false
,則返回String.Empty
,如果該屬性的值為true
,則調用的邏輯是Value.ToString
。 見下面的例子:
2 Console.WriteLine(i.ToString);
3 //輸出結果:10
4
5 i = null;
6 Console.WriteLine(i.ToString == string.Empty);
7 //輸出結果:True
System.Nullable
的靜態類,包括三個方法:
2 {
3 //返回指定的可空類型的基礎類型參數。
4 public static Type GetUnderlyingType(Type nullableType);
5
6 //比較兩個相對值 System.Nullable
7 public static int Compare
8
9 //指示兩個指定 System.Nullable
10 public static bool Equals
11 }
GetUnderlyingType(Type nullableType)
方法,另外兩個方法是用來比較值的,大家可以自己研究。GetUnderlyingType(Type nullableType)
方法是用來返回一個可為空類型的基礎類型,如果nullableType
參數不是一個封閉的Nullablenull
。
2 //輸出結果:System.Int32
3
4 Console.WriteLine(Nullable.GetUnderlyingType(typeof(Nullable<>)) == null);
5 //輸出結果:True
6
7 Console.WriteLine(Nullable.GetUnderlyingType(typeof(int)) == null);
8 //輸出結果:True
9
10 Console.WriteLine(Nullable.GetUnderlyingType(typeof(string)) == null);
11 //輸出結果:True
簡寫
編譯後的語句
1 int? i = 5; 2 3 int? j = null; 4 5 var r = i != null; 6 7 var v = (int) i; 8 9 i++; 10 11 i = i + 3; 12 13 r = i != j; 14 15 r = i >= j; 16 17 var k = i + j; 18 19 double? x = 5; 20 21 double? y = j;
1 int? i = new int?(5); 2 3 int? j = new int?; 4 5 var r = i.HasValue; 6 7 var v = i.Value; 8 9 i = i.HasValue ? new int?(i.GetValueOrDefault + 1) : new int?; 10 11 i = i.HasValue ? new int?(i.GetValueOrDefault + 3) : new int?; 12 13 r = i.GetValueOrDefault != j.GetValueOrDefault || i.HasValue != j.HasValue; 14 15 r = i.GetValueOrDefault >= j.GetValueOrDefault && i.HasValue & j.HasValue; 16 17 int? k = i.HasValue & j.HasValue ? new int?(i.GetValueOrDefault + j.GetValueOrDefault) : new int?; 18 19 double? x = new double?((double) 5); 20 21 double? y = j.HasValue ? new double?((double) j.GetValueOrDefault) : new double?;
※Javascript 「繼承」
※使用CoApp創建NuGet C++靜態庫包
※大話Python正則表達式
※Linux 最新SO_REUSEPORT特性
※java中方法總結
TAG:達人科技 |
※iOS 12的新功能「Screen Time」的詳細說明!
※蘋果支持文檔詳細說明Apple Card返現規則
※和「植物殺手」 say goodbye 細說如何養好植物的那些事篇一
※PC版Xbox遊戲通行證 全新Win10 Xbox APP功能詳細說明
※細說win7和win10哪個好!
※iPad Pro機身為什麼會彎曲?蘋果給出詳細說明~
※7月6日@北京SKP RENDEZ-VOUS:細說芭蕾之美華麗Talk
※細說A-Level,請耐心看完。不懂再問我
※細說LVS-DR之VIP、DIP跨網段實例
※山東如意或將「半價」收購Topshop母公司?細說背後緣由
※4月27日 報名【華麗Talk】@北京SKP RENDEZ-VOUS:細說小眾香水的前世今生+全球奢侈茶葉品牌TWG品鑒
※報名:4月27日【華麗Talk】細說小眾香水的前世今生@北京SKP RENDEZ-VOUS
※3D虎細說3DTALK 系列產品的發展史
※4月27日 報名華麗Talk@北京SKP RENDEZ-VOUS:細說小眾香水的前世今生+全球奢侈茶葉品牌TWG品鑒
※報名:4月27日華麗Talk細說小眾香水的前世今生@北京SKP RENDEZ-VOUS
※Lucene倒排索引簡述 細說倒排索引構建
※細說「去中心化金融」系列一:De.Fi概念的緣起和分類
※微軟官方有關Xbox One為開發者加入滑鼠和鍵盤支持的詳細說明
※連續三年每年業績翻番!摩納哥時尚珠寶品牌 APM Monaco 家族掌門人細說奧秘
※vivo NEX發布會上都沒有細說的黑科技,被扒出來了!