欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#基礎(chǔ)知識(shí) 全面解析可空類(lèi)型

 更新時(shí)間:2012年11月23日 14:57:24   作者:  
C# 2.0 中還引入了可空類(lèi)型,可空類(lèi)型也是值類(lèi)型,只是可空類(lèi)型是包括null的值類(lèi)型的,下面就介紹下C#2.0中對(duì)可空類(lèi)型的支持具體有哪些內(nèi)容

引言:

  C# 2.0 中還引入了可空類(lèi)型,可空類(lèi)型也是值類(lèi)型,只是可空類(lèi)型是包括null的值類(lèi)型的,下面就介紹下C#2.0中對(duì)可空類(lèi)型的支持具體有哪些內(nèi)容(最近一直都在思考如何來(lái)分享這篇文章的,因?yàn)閯傞_(kāi)始覺(jué)得可空類(lèi)型使用過(guò)程中比較簡(jiǎn)單,覺(jué)得沒(méi)有講的必要,但是考慮到這個(gè)系列的完整性,決定還是嘮叨下吧,希望對(duì)一些不熟悉的人有幫助)。

一、為什么會(huì)有可空類(lèi)型

   如果朋友們看了我之前的分享,對(duì)于這一部分都不會(huì)陌生,因?yàn)槲乙话憬榻BC#特性經(jīng)常會(huì)以這樣的方式開(kāi)頭的, 因?yàn)槊總€(gè)特性都是有它出現(xiàn)的原因的(有一句佛語(yǔ)這是這么講的:萬(wàn)事皆有因,有因必有果),首先來(lái)說(shuō)說(shuō)這個(gè)因的(果當(dāng)然是新增加了可空類(lèi)型這個(gè)新特性了。),當(dāng)我們?cè)谠O(shè)計(jì)數(shù)據(jù)庫(kù)的時(shí)候,我們可以設(shè)置數(shù)據(jù)庫(kù)字段允許為null值,如果數(shù)據(jù)庫(kù)字段是日期等這樣在C#語(yǔ)言是值類(lèi)型時(shí),當(dāng)我們把數(shù)據(jù)庫(kù)表映射一個(gè)對(duì)象時(shí),此時(shí)Datetime類(lèi)型在C# 語(yǔ)言中是不能為null的,如果這樣就會(huì)與數(shù)據(jù)庫(kù)的設(shè)計(jì)有所沖突,這樣開(kāi)發(fā)人員就會(huì)有這樣的需求了——值類(lèi)型能不能也為可空類(lèi)型的?同時(shí)微軟也看出了用戶(hù)有這樣的需求,所以微軟在C# 2.0中就新增加了一種類(lèi)型——可空類(lèi)型,即包含null值的值類(lèi)型,這個(gè)也就是我理解的因了,介紹完因之后,當(dāng)然就是好好嘮叨下可空類(lèi)型是個(gè)什么東西的了?

二、可空類(lèi)型的介紹

   可空類(lèi)型也是值類(lèi)型,只是它是包含null的一個(gè)值類(lèi)型。我們可以像下面這樣表示可空類(lèi)型(相信大家都不陌生):

復(fù)制代碼 代碼如下:

int? nullable = null;

  上面代碼 int? 就是可空的int類(lèi)型(有人可能會(huì)這樣的疑問(wèn)的, 如果在C#1中我硬要讓一個(gè)值類(lèi)型為一個(gè)可空類(lèi)型怎么辦到呢?當(dāng)然這個(gè)在C#1之前也是有可以辦到的,只是會(huì)相當(dāng)麻煩,對(duì)于這個(gè)如果有興趣的朋友可以去刨下根),然而其實(shí) "?"這個(gè)修飾符只是C#提供的一個(gè)語(yǔ)法糖(所謂語(yǔ)法糖,就是C#提供的一種方便的形式,其實(shí)肯定沒(méi)有int? 這個(gè)類(lèi)型,這個(gè)int?編譯器認(rèn)為的就是Nullable<int>類(lèi)型,即可空類(lèi)型),其實(shí)真真C# 2.0提供的可空類(lèi)型是——Nullable<T>(這個(gè)T就是上專(zhuān)題介紹的泛型參數(shù),其中T只能為值類(lèi)型,因?yàn)閺目煽疹?lèi)型的定義為:public struct Nullable<T> where T : struct)和Nullable。下面給出一段代碼來(lái)介紹可空類(lèi)型的使用:

復(fù)制代碼 代碼如下:

namespace 可空類(lèi)型Demo
{
class Program
{
static void Main(string[] args)
{
// 下面代碼也可以這樣子定義int? value=1;
Nullable<int> value = 1;

Console.WriteLine("可空類(lèi)型有值的輸出情況:");
Display(value);
Console.WriteLine();
Console.WriteLine();

value = new Nullable<int>();
Console.WriteLine("可空類(lèi)型沒(méi)有值的輸出情況:");
Display(value);
Console.Read();
}

// 輸出方法,演示可空類(lèi)型中的方法和屬性的使用
private static void Display(int? nullable)
{
// HasValue 屬性代表指示可空對(duì)象是否有值
// 在使用Value屬性時(shí)必須先判斷可空類(lèi)型是否有值,
// 如果可空類(lèi)型對(duì)象的HasValue返回false時(shí),將會(huì)引發(fā)InvalidOperationException異常
Console.WriteLine("可空類(lèi)型是否有值:{0}", nullable.HasValue);
if (nullable.HasValue)
{
Console.WriteLine("值為: {0}", nullable.Value);
}

// GetValueOrDefault(代表如果可空對(duì)象有值,就用它的值返回,如果可空對(duì)象不包含值時(shí),使用默認(rèn)值0返回)相當(dāng)與下面的語(yǔ)句
// if (!nullable.HasValue)
// {
// result = d.Value;
// }

Console.WriteLine("GetValueorDefault():{0}", nullable.GetValueOrDefault());

// GetValueOrDefault(T)方法代表如果 HasValue 屬性為 true,則為 Value 屬性的值;否則為 defaultValue 參數(shù)值,即2。
Console.WriteLine("GetValueorDefalut重載方法使用:{0}", nullable.GetValueOrDefault(2));

// GetHashCode()代表如果 HasValue 屬性為 true,則為 Value 屬性返回的對(duì)象的哈希代碼;如果 HasValue 屬性為 false,則為零
Console.WriteLine("GetHashCode()方法的使用:{0}", nullable.GetHashCode());
}
}
}

輸出結(jié)果:

上面的演示代碼中都注釋,這里就不再解釋了,為了讓大家明白進(jìn)一步理解可空類(lèi)型是值類(lèi)型,下面貼出中間語(yǔ)言代碼截圖:

三、空合并操作符(?? 操作符)

  ??操作符也就是"空合并操作符",它代表的意思是兩個(gè)操作數(shù),如果左邊的數(shù)不為null時(shí),就返回左邊的數(shù),如果左邊的數(shù)為null,就返回右邊的數(shù),這個(gè)操作符可以用于可空類(lèi)型,也可以用于引用類(lèi)型,但是不能用于值類(lèi)型(之所以不能應(yīng)用值類(lèi)型(這里除了可空類(lèi)型),因?yàn)??運(yùn)算符要對(duì)左邊的數(shù)與null進(jìn)行比較,然而值類(lèi)型,不能與null類(lèi)型比較,所以就不支持??運(yùn)算符),下面用一個(gè)例子來(lái)掩飾下??運(yùn)算符的使用(??這個(gè)運(yùn)算符可以方便我們?cè)O(shè)置默認(rèn)值,可以避免在代碼中寫(xiě)if, else語(yǔ)句,簡(jiǎn)單代碼數(shù)量,從而有利于閱讀。)

復(fù)制代碼 代碼如下:

static void Main(string[] args)
{
Console.WriteLine("??運(yùn)算符的使用如下:");
NullcoalescingOperator();
Console.Read();
}

private static void NullcoalescingOperator()
{
int? nullable = null;
int? nullhasvalue = 1;

// ??和三目運(yùn)算符的功能差不多的
// 所以下面代碼等價(jià)于:
// x=nullable.HasValue?b.Value:12;
int x = nullable ?? 12;

// 此時(shí)nullhasvalue不能null,所以y的值為nullhasvalue.Value,即輸出1
int y = nullhasvalue ?? 123;
Console.WriteLine("可空類(lèi)型沒(méi)有值的情況:{0}",x);
Console.WriteLine("可空類(lèi)型有值的情況:{0}", y);

// 同時(shí)??運(yùn)算符也可以用于引用類(lèi)型, 下面是引用類(lèi)型的例子
Console.WriteLine();
string stringnotnull = "123";
string stringisnull = null;

// 下面的代碼等價(jià)于:
// (stringnotnull ==null)? "456" :stringnotnull
// 同時(shí)下面代碼也等價(jià)于:
// if(stringnotnull==null)
// {
// return "456";
// }
// else
// {
// return stringnotnull;
// }
// 從上面的等價(jià)代碼可以看出,有了??運(yùn)算符之后可以省略大量的if—else語(yǔ)句,這樣代碼少了, 自然可讀性就高了
string result = stringnotnull ?? "456";
string result2 = stringisnull ?? "12";
Console.WriteLine("引用類(lèi)型不為null的情況:{0}", result);
Console.WriteLine("引用類(lèi)型為null的情況:{0}", result2);
}

下面是運(yùn)行結(jié)果截圖:

四、可空類(lèi)型的裝箱和拆箱

   值類(lèi)型存在裝箱和拆箱的過(guò)程,可空類(lèi)型也屬于值類(lèi)型,從而也有裝箱和拆箱的過(guò)程的, 這里先介紹下裝箱和拆箱的概念的, 裝箱指的的從值類(lèi)型到引用類(lèi)型的過(guò)程,拆箱當(dāng)然也就是裝箱的反過(guò)程,即從引用類(lèi)型到值類(lèi)型的過(guò)程(這里進(jìn)一步解釋下我理解的裝箱和拆箱,首先.Net中值類(lèi)型是分配在堆棧上的,然而引用類(lèi)型分配在托管堆上,裝箱過(guò)程就是把值類(lèi)型的值從推棧上拷貝到托管堆上,然后推棧上存儲(chǔ)的是對(duì)托管堆上拷貝值的引用,然而拆箱就是把托管堆上的值拷貝到堆棧上.簡(jiǎn)單一句話(huà)概況,裝箱和拆箱就是一個(gè)值的拷貝的一個(gè)過(guò)程,就想搬家一樣,把東西從一個(gè)地方搬到另一個(gè)地方,對(duì)于深入的理解,大家可以參考下園中的博文.), 括號(hào)中是我理解的裝箱和拆箱的過(guò)程,下面就具體介紹下可空類(lèi)型的裝箱和拆箱的:

  當(dāng)把一個(gè)可空類(lèi)型賦給一個(gè)引用類(lèi)型變量時(shí),此時(shí)CLR 會(huì)對(duì)可空類(lèi)型(Nullable<T>)對(duì)象進(jìn)行裝箱處理,首先CLR會(huì)檢測(cè)可空類(lèi)型是否為null,如果為null,CLR則不進(jìn)行實(shí)際的裝箱操作(因?yàn)閚ull可以直接賦給一個(gè)引用類(lèi)型變量),如果不為null,CLR會(huì)從可空類(lèi)型對(duì)象中獲取值,并對(duì)該值進(jìn)行裝箱(這個(gè)過(guò)程就是值類(lèi)型的裝箱過(guò)程了。),當(dāng)把一個(gè)已裝箱的值類(lèi)型賦給一個(gè)可空類(lèi)型變量時(shí),此時(shí)CLR會(huì)對(duì)已裝箱的值類(lèi)型進(jìn)行拆箱處理,如果已裝箱值類(lèi)型的引用為null,此時(shí)CLR會(huì)把可空類(lèi)型設(shè)為null(如果覺(jué)得啰嗦,大家可以直接看下面的代碼,代碼中也會(huì)有詳細(xì)的注釋?zhuān)?。下面用一個(gè)示例來(lái)演示下可空類(lèi)型的裝箱和拆箱的使用,這樣可以幫助大家更好的理解前面介紹的概念:

復(fù)制代碼 代碼如下:

static void Main(string[] args)
{
//Console.WriteLine("??運(yùn)算符的使用如下:");
//NullcoalescingOperator();
Console.WriteLine("可空類(lèi)型的裝箱和拆箱的使用如下:");
BoxedandUnboxed();
Console.Read();
}

// 可空類(lèi)型裝箱和拆箱的演示
private static void BoxedandUnboxed()
{
// 定義一個(gè)可空類(lèi)型對(duì)象nullable
Nullable<int> nullable = 5;
int? nullablewithoutvalue = null;

// 獲得可空對(duì)象的類(lèi)型,此時(shí)返回的是System.Int32,而不是System.Nullable<System.Int32>,這點(diǎn)大家要特別注意下的
Console.WriteLine("獲取不為null的可空類(lèi)型的類(lèi)型為:{0}",nullable.GetType());

// 對(duì)于一個(gè)為null的類(lèi)型調(diào)用方法時(shí)出現(xiàn)異常,所以一般對(duì)于引用類(lèi)型的調(diào)用方法前,最好養(yǎng)成習(xí)慣先檢測(cè)下它是否為null
//Console.WriteLine("獲取為null的可空類(lèi)型的類(lèi)型為:{0}", nullablewithoutvalue.GetType());

// 將可空類(lèi)型對(duì)象賦給引用類(lèi)型obj,此時(shí)會(huì)發(fā)生裝箱操作,大家可以通過(guò)IL中的boxed 來(lái)證明
object obj = nullable;

// 獲得裝箱后引用類(lèi)型的類(lèi)型,此時(shí)輸出的仍然是System.Int32,而不是System.Nullable<System.Int32>
Console.WriteLine("獲得裝箱后obj 的類(lèi)型:{0}", obj.GetType());

// 拆箱成非可空變量
int value = (int)obj;
Console.WriteLine("拆箱成非可空變量的情況為:{0}", value);

// 拆箱成可空變量
nullable = (int?)obj;
Console.WriteLine("拆箱成可空變量的情況為:{0}", nullable);

// 裝箱一個(gè)沒(méi)有值的可空類(lèi)型的對(duì)象
obj = nullablewithoutvalue;
Console.WriteLine("對(duì)null的可空類(lèi)型裝箱后obj 是否為null:{0}", obj==null);

// 拆箱成非可空變量,此時(shí)會(huì)拋出NullReferenceException異常,因?yàn)闆](méi)有值的可空類(lèi)型裝箱后obj等于null,引用一個(gè)空地址
// 相當(dāng)于拆箱后把null值賦給一個(gè)int 類(lèi)型的變量,此時(shí)當(dāng)然就會(huì)出現(xiàn)錯(cuò)誤了
//value = (int)obj;
//Console.WriteLine("一個(gè)沒(méi)有值的可空類(lèi)型裝箱后,拆箱成非可空變量的情況為:{0}", value);

// 拆箱成可空變量
nullable = (int?)obj;
Console.WriteLine("一個(gè)沒(méi)有值的可空類(lèi)型裝箱后,拆箱成可空變量是否為null:{0}", nullable == null);
}
運(yùn)行結(jié)果:

   上面代碼中都有注釋的, 而且代碼也比較簡(jiǎn)單, 這里就不解釋了, 其實(shí)可空類(lèi)型的裝箱和拆箱操作大家可以就理解為非可空值類(lèi)型的裝箱和拆箱的過(guò)程,只是對(duì)于非可空類(lèi)型因?yàn)榘琻ull值,所以CLR會(huì)提前對(duì)它進(jìn)行檢查下它是否為空,為null就不不任何處理,如果不為null,就按照非可空值類(lèi)型的裝箱和拆箱的過(guò)程來(lái)裝箱和拆箱。

五、小結(jié)

   到這里本專(zhuān)題的介紹就完成了,本專(zhuān)題主要介紹了下可空類(lèi)型以及可空類(lèi)型相關(guān)的知識(shí),希望這篇文章可以幫助大家對(duì)可空類(lèi)型的認(rèn)識(shí)可以更加全面,下一個(gè)專(zhuān)題將和大家介紹下匿名方法, 匿名方法也是Lambda表達(dá)式和Linq的一個(gè)鋪墊,然而它是C#2中被提出來(lái)了的, 從而可以看出Lambda和Linq在C# 3.0中被添加其實(shí)是微軟早在C# 2.0的時(shí)候就計(jì)劃好了的,早就計(jì)劃好了的(這也是我的推斷,然而我覺(jué)得為什么它不直接在把Lambda和Linq都放在C# 2中提出來(lái)的, 卻偏偏放在C# 3.0中提出,我理解原因有——1 覺(jué)得微軟當(dāng)時(shí)肯定是想一起提出的,但是后面發(fā)現(xiàn)這幾個(gè)新的特性提出后會(huì)對(duì)編譯器做比較大的改動(dòng),需要比較長(zhǎng)的時(shí)間來(lái)實(shí)現(xiàn),此時(shí)又怕用戶(hù)等不及了,覺(jué)得C#很多東西都沒(méi)有,所以微軟就先把做好了的部分先發(fā)布出來(lái),然而把Lambda和Linq放到C#3來(lái)提出。我推理覺(jué)得應(yīng)該是這樣的,所以C#的所有特性都是緊密相連的。)

相關(guān)文章

  • 在winform下實(shí)現(xiàn)左右布局多窗口界面的方法

    在winform下實(shí)現(xiàn)左右布局多窗口界面的方法

    在web頁(yè)面上我們可以通過(guò)frameset,iframe嵌套框架很容易實(shí)現(xiàn)各種導(dǎo)航+內(nèi)容的布局界面,而在winform、WPF中實(shí)現(xiàn)其實(shí)也很容易,通過(guò)本文給大家介紹在winform下實(shí)現(xiàn)左右布局多窗口界面的方法,本文介紹的非常詳細(xì),對(duì)winform布局相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • C#中的Task使用方式

    C#中的Task使用方式

    本文介紹了C#中的Task,這是一種異步編程模型,允許你在不阻塞主線(xiàn)程的情況下執(zhí)行耗時(shí)的操作,文章詳細(xì)介紹了如何創(chuàng)建、等待、處理異常、延續(xù)以及并行執(zhí)行Task
    2024-12-12
  • RandomId生成隨機(jī)字符串詳解實(shí)例

    RandomId生成隨機(jī)字符串詳解實(shí)例

    本文主要介紹RandomId 生成隨機(jī)字符串的方法,大家參考使用吧
    2013-12-12
  • Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享

    Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享

    這篇文章主要介紹了Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享的相關(guān)資料,需要的朋友可以參考下
    2015-03-03
  • 基于C#實(shí)現(xiàn)PDF文件合并工具

    基于C#實(shí)現(xiàn)PDF文件合并工具

    這篇文章主要為大家詳細(xì)介紹了如何基于C#實(shí)現(xiàn)一個(gè)簡(jiǎn)單的PDF文件合并工具,文中的示例代碼簡(jiǎn)潔易懂,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-01-01
  • C#使用Aspose.Cells創(chuàng)建和讀取Excel文件

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

    這篇文章主要為大家詳細(xì)介紹了C#使用Aspose.Cells創(chuàng)建和讀取Excel文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • 詳解c# 數(shù)組(Array)

    詳解c# 數(shù)組(Array)

    這篇文章主要介紹了c# 數(shù)組的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C# javascript 讀寫(xiě)Cookie的方法

    C# javascript 讀寫(xiě)Cookie的方法

    這篇文章介紹了C# javascript 讀寫(xiě)Cookie的方法,有需要的朋友可以參考一下
    2013-10-10
  • C#封裝將函數(shù)封裝為接口dll的簡(jiǎn)單步驟指南

    C#封裝將函數(shù)封裝為接口dll的簡(jiǎn)單步驟指南

    在C#中,封裝函數(shù)為接口并打包成DLL是實(shí)現(xiàn)代碼重用和模塊化的常見(jiàn)方法,此過(guò)程包括創(chuàng)建類(lèi)庫(kù)項(xiàng)目、定義接口、實(shí)現(xiàn)接口、編譯項(xiàng)目生成DLL文件,這種方法適用于需要在多個(gè)項(xiàng)目間共享功能時(shí)使用,需要的朋友可以參考下
    2024-11-11
  • C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路

    C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路

    這篇文章主要介紹了C#?將Excel轉(zhuǎn)為PDF時(shí)自定義表格紙張大小的代碼思路,轉(zhuǎn)換前的頁(yè)面大小設(shè)置為該版本中寫(xiě)入的新功能,在舊版本和免費(fèi)版本中暫不支持,感興趣的朋友跟隨小編一起看看實(shí)例代碼
    2021-11-11

最新評(píng)論