最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

.NET中可空值類型【Nullable<T>】實現(xiàn)原理

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:35:53
文檔

.NET中可空值類型【Nullable<T>】實現(xiàn)原理

.NET中可空值類型【Nullable<T>】實現(xiàn)原理:為了讓.Net中的值類型可以賦值為null,微軟特地添加了Nullable<T>類型,也可簡寫為T?。但是Nullable<T>自身是結(jié)構(gòu)體,也是值類型,那么它是如何實現(xiàn)將null賦值給值類型的呢? 下面通過自定義一個可空值類型來講解Nullable<T
推薦度:
導(dǎo)讀.NET中可空值類型【Nullable<T>】實現(xiàn)原理:為了讓.Net中的值類型可以賦值為null,微軟特地添加了Nullable<T>類型,也可簡寫為T?。但是Nullable<T>自身是結(jié)構(gòu)體,也是值類型,那么它是如何實現(xiàn)將null賦值給值類型的呢? 下面通過自定義一個可空值類型來講解Nullable<T

為了讓.Net中的值類型可以賦值為null,微軟特地添加了Nullable<T>類型,也可簡寫為T?。但是Nullable<T>自身是結(jié)構(gòu)體,也是值類型,那么它是如何實現(xiàn)將null賦值給值類型的呢?

下面通過自定義一個可空值類型來講解Nullable<T>的實現(xiàn)原理。

自定義可空值類型

struct XfhNullable<T> where T : struct
{
 private T innerValue;
 //這個屬性很重要
 public bool HasValue { set; get; }
 public T Value
 {
 get
 {
 return HasValue ? innerValue: throw new InvalidOperationException();
 }
 }
 public XfhNullable(T value)
 {
 this.innerValue= value;
 HasValue = true;
 }
 public T GetValueOrDefault(T value)
 {
 return HasValue ? this.innerValue: value;
 }
 public T GetValueOrDefault()
 {
 return this.innerValue;
 }
}

一個可空值類型的結(jié)構(gòu)體大致功能已經(jīng)定義好了,下面我們來創(chuàng)建可空值類型的實例來驗證下。

using static System.Console;
class Program
{
 static void Main()
 {
 //使用結(jié)構(gòu)體默認(rèn)的無參構(gòu)造函數(shù)進行實例化
 XfhNullable<int> num = new XfhNullable<int>();
 WriteLine(num.HasValue);
 WriteLine(null_num.GetValueOrDefault());
 }
}

可以看到,變量num并不含有值,調(diào)用GetValueOrDefault()則會獲取它的默認(rèn)值 0;

這時我們將null賦值給變量num會發(fā)現(xiàn)編譯器報錯Cannot convert null to 'XfhNullable<int>' because it is a non-nullable value type這是因為編譯器把我們定義的結(jié)構(gòu)體XfhNullable<T>看作是普通值類型而非可空值類型,所以我們還要添加可空值類型和XfhNullable<T>之間的轉(zhuǎn)換功能。

public static implicit operator XfhNullable<T>(T? nullabelValue)
{
 if (nullabelValue== null)
 {
 return new XfhNullable<T>();
 }
 return new XfhNullable<T>(nullabelValue.Value);
}

上面的代碼實現(xiàn)了可空值類型向XfhNullable<T>的隱式轉(zhuǎn)換,添加上面代碼之后發(fā)現(xiàn)編譯器不再報錯。XfhNullable<T>已經(jīng)成為一個可為null的值類型。

static void Main()
{
 XfhNullable<int> null_num = null;
 WriteLine(null_num.HasValue);
}

XfhNullable<T>中的屬性HasValue的作用就是標(biāo)記當(dāng)前類型是否為null,若是則返回False,否則返回True。當(dāng)HasValue為False時調(diào)用該類型的Value屬性則會拋出異常InvalidOperationException。但可調(diào)用GetValueOrDefault()方法來獲取類型的默認(rèn)值。

Nullable<T>類型可以通過運算符==來判斷值是否為null,我們也可以通過運算符重載來實現(xiàn)該功能:

public static bool operator ==(XfhNullable<T> cn, object obj)
{
 if (cn.HasValue)
 {
 return false;
 }
 return true;
}
public static bool operator !=(XfhNullable<T> cn, object obj)
{
 return !(cn == obj);
}
static void Main()
{
 XfhNullable<int> null_num = null;
 WriteLine(null_num == null);
}

接下來,我們來實現(xiàn)普通值類型和XfhNullable<T>之間的轉(zhuǎn)換:

public static implicit operator XfhNullable<T>(T value)
{
 return new XfhNullable<T>(value);
}
public static explicit operator T(XfhNullable<T> value)
{
 return value.innerValue;
}
static void Main()
{
 XfhNullable<int> null_num = null;
 null_num = 12;//int類型隱式轉(zhuǎn)換為XfhNullable<int>類型
 WriteLine(null_num == null);
 WriteLine(null_num.Value);
 int i = (int)null_num;//XfhNullable<int>類型強制轉(zhuǎn)換為int類型
 WriteLine(i);
}

獲取實例在運行時的類型:

static void Main()
{
 XfhNullable<int> null_num = 12;
 WriteLine(null_num.GetType());
}

這個返回值不大友好,我們希望這里返回內(nèi)置的值類型,System.Int32,具體實現(xiàn)代碼如下:

//因為Object類中的GetType方法不允許子類重寫(避免子類隱藏自己的實際類型)
//所以這里使用關(guān)鍵字new來隱藏Object類中的GetType方法
public new Type GetType()
{
 return innerValue.GetType();
}

結(jié)論:沒有可為空的值類型

至此,我們已經(jīng)自定義了一個可為空的值類型XfhNullable<T>,通過以上代碼,我們不難發(fā)現(xiàn)所謂可為空的值類型是不存在的,它是通過屬性HasValue來對null值進行標(biāo)記的,其內(nèi)部通過字段innerValue(該字段對應(yīng)Nullable<T>中的value字段)來維護該類型的值,若被賦值為null則innerValue初始化為值類型的初始值。換句話說,Nullable<T>只是在邏輯層面上實現(xiàn)了把null賦值給值類型,給我們一種值類型可為null的感覺。

最后說下可空值類型的裝箱與拆箱。

CLR在對Nullable<T>實例執(zhí)行裝箱操作時首先檢查它是否為null,若是則CLR不裝箱任何東西而是直接返回null;若實例的值不是null則獲取該實例的值(Value屬性)并對這個值進行裝箱操作。

拆箱時,對于null則返回一個Nullable<T>()實例,對于一個具體的數(shù)值,如5,則返回Nullable<T>(5)實例。

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

.NET中可空值類型【Nullable<T>】實現(xiàn)原理

.NET中可空值類型【Nullable<T>】實現(xiàn)原理:為了讓.Net中的值類型可以賦值為null,微軟特地添加了Nullable<T>類型,也可簡寫為T?。但是Nullable<T>自身是結(jié)構(gòu)體,也是值類型,那么它是如何實現(xiàn)將null賦值給值類型的呢? 下面通過自定義一個可空值類型來講解Nullable<T
推薦度:
標(biāo)簽: 原理 類型 tt
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top