自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺談C#泛型的用處

開發(fā) 后端
本文將介紹C#泛型的用處,C#泛型類在編譯時(shí),先生成中間代碼IL,通用類型T只是一個(gè)占位符。靈活運(yùn)用泛型能提高的大家的編程效率。

為什么要使用C#泛型?

為了了解這個(gè)問題,我們先看下面的代碼,代碼省略了一些內(nèi)容,但功能是實(shí)現(xiàn)一個(gè)棧,這個(gè)棧只能處理int數(shù)據(jù)類型:

  1. public class Stack  
  2.     {  
  3.         private int[] m_item;  
  4.         public int Pop(){...}  
  5.         public void Push(int item){...}  
  6.         public Stack(int i)  
  7.         {  
  8.             this.m_item = new int[i];  
  9.         }  

上面代碼運(yùn)行的很好,但是,當(dāng)我們需要一個(gè)棧來保存string類型時(shí),該怎么辦呢?很多人都會(huì)想到把上面的代碼復(fù)制一份,把int改成string不就行了。當(dāng)然,這樣做本身是沒有任何問題的,但一個(gè)優(yōu)秀的程序是不會(huì)這樣做的,因?yàn)樗氲饺粢院笤傩枰猯ong、Node類型的棧該怎樣做呢?還要再?gòu)?fù)制嗎??jī)?yōu)秀的程序員會(huì)想到用一個(gè)通用的數(shù)據(jù)類型object來實(shí)現(xiàn)這個(gè)棧:

  1. public class Stack  
  2.     {  
  3.         private object[] m_item;  
  4.         public object Pop(){...}  
  5.         public void Push(object item){...}  
  6.         public Stack(int i)  
  7.         {  
  8.             this.m_item = new[i];  
  9.         }  
  10.     } 

這個(gè)棧寫的不錯(cuò),他非常靈活,可以接收任何數(shù)據(jù)類型,可以說是一勞永逸。但全面地講,也不是沒有缺陷的,主要表現(xiàn)在:

當(dāng)Stack處理值類型時(shí),會(huì)出現(xiàn)裝箱、折箱操作,這將在托管堆上分配和回收大量的變量,若數(shù)據(jù)量大,則性能損失非常嚴(yán)重。

在處理引用類型時(shí),雖然沒有裝箱和折箱操作,但將用到數(shù)據(jù)類型的強(qiáng)制轉(zhuǎn)換操作,增加處理器的負(fù)擔(dān)。

在數(shù)據(jù)類型的強(qiáng)制轉(zhuǎn)換上還有更嚴(yán)重的問題(假設(shè)stack是Stack的一個(gè)實(shí)例):

  1. Node1 x = new Node1();  
  2.             stack.Push(x);  
  3.          Node2 y = (Node2)stack.Pop(); 

上面的代碼在編譯時(shí)是完全沒問題的,但由于Push了一個(gè)Node1類型的數(shù)據(jù),但在Pop時(shí)卻要求轉(zhuǎn)換為Node2類型,這將出現(xiàn)程序運(yùn)行時(shí)的類型轉(zhuǎn)換異常,但卻逃離了編譯器的檢查。

針對(duì)object類型棧的問題,我們引入泛型,他可以優(yōu)雅地解決這些問題。泛型用用一個(gè)通過的數(shù)據(jù)類型T來代替object,在類實(shí)例化時(shí)指定T的類型,運(yùn)行時(shí)(Runtime)自動(dòng)編譯為本地代碼,運(yùn)行效率和代碼質(zhì)量都有很大提高,并且保證數(shù)據(jù)類型安全。

使用C#泛型

下面是用泛型來重寫上面的棧,用一個(gè)通用的數(shù)據(jù)類型T來作為一個(gè)占位符,等待在實(shí)例化時(shí)用一個(gè)實(shí)際的類型來代替。讓我們來看看泛型的威力:

  1. public class Stack  
  2.     {  
  3.         private T[] m_item;  
  4.         public T Pop(){...}  
  5.         public void Push(T item){...}  
  6.         public Stack(int i)  
  7.         {  
  8.             this.m_item = new T[i];  
  9.         }  

類的寫法不變,只是引入了通用數(shù)據(jù)類型T就可以適用于任何數(shù)據(jù)類型,并且類型安全的。這個(gè)類的調(diào)用方法:

  1. //實(shí)例化只能保存int類型的類  
  2. Stack a = new Stack(100);  
  3.       a.Push(10);  
  4.       a.Push("8888"); //這一行編譯不通過,因?yàn)轭恆只接收int類型的數(shù)據(jù)  
  5.       int x = a.Pop();  
  6. //實(shí)例化只能保存string類型的類  
  7. Stack b = new Stack(100);  
  8. b.Push(10);    //這一行編譯不通過,因?yàn)轭恇只接收string類型的數(shù)據(jù)  
  9.       b.Push("8888");  
  10. string y = b.Pop(); 

這個(gè)類和object實(shí)現(xiàn)的類有截然不同的區(qū)別:

1. 他是類型安全的。實(shí)例化了int類型的棧,就不能處理string類型的數(shù)據(jù),其他數(shù)據(jù)類型也一樣。

2.無需裝箱和折箱。這個(gè)類在實(shí)例化時(shí),按照所傳入的數(shù)據(jù)類型生成本地代碼,本地代碼數(shù)據(jù)類型已確定,所以無需裝箱和折箱。

3. 無需類型轉(zhuǎn)換。

理論知識(shí):

所謂泛型:即通過參數(shù)化類型來實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。泛型編程是一種編程范式,它利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)更為靈活的復(fù)用。

C#泛型賦予了代碼更強(qiáng)的類型安全,更好的復(fù)用,更高的效率,更清晰的約束。

C#泛型能力由CLR在運(yùn)行時(shí)支持,區(qū)別于C++的編譯時(shí)模板機(jī)制,和java的編譯時(shí)的“搽拭法”。這使得泛型能力可以在各個(gè)支持CLR的語言之間進(jìn)行無縫的互操作。

C#泛型代碼在被編譯為IL和元數(shù)據(jù)時(shí),采用特殊的占位符來表示泛型類型,并用專有的IL指令支持泛型操作。而真正的泛型實(shí)例化工作以“on-demand”的方式,發(fā)生在JIT編譯時(shí)。

C#泛型編譯機(jī)制如下:

***輪編譯時(shí),編譯器只為Stack類型產(chǎn)生“泛型版”的IL代碼和元數(shù)據(jù),并不進(jìn)行泛型類型的實(shí)例化,T在中間只充當(dāng)占位符。

JIT編譯時(shí),當(dāng)JIT編譯器***次遇到Stack時(shí),將用int類型替換“泛型版”IL代碼與元數(shù)據(jù)中的T -- 進(jìn)行泛型類型的實(shí)例化。

CLR為所有類型參數(shù)為“引用類型”的泛型類型產(chǎn)生同一份代碼,但如果類型參數(shù)為“值類型”,對(duì)每一個(gè)不同的“值類型”,CLR將為其產(chǎn)生一份獨(dú)立的代碼。

C#泛型的幾個(gè)特點(diǎn)

如果實(shí)例化泛型類型的參數(shù)相同,那么JIT編譯器會(huì)重復(fù)使用該類型,因此C#的動(dòng)態(tài)泛型能力避免了C++靜態(tài)模板可能導(dǎo)致的代碼膨脹的問題。

C#泛型類型攜帶有豐富的元數(shù)據(jù),因此C#的泛型類型可以應(yīng)用于強(qiáng)大的反射技術(shù)。

C#的泛型采用“基類、接口、構(gòu)造器、值類型/引用類型”的約束方式來實(shí)現(xiàn)對(duì)類型參數(shù)的“顯示約束”,提高了類型安全的同時(shí),也喪失了C++模板基于“簽名”的隱式約束所具有的高靈活性。

C#泛型類在編譯時(shí),先生成中間代碼IL,通用類型T只是一個(gè)占位符。在實(shí)例化類時(shí),根據(jù)用戶指定的數(shù)據(jù)類型代替T并由即時(shí)編譯器(JIT)生成本地代碼,這個(gè)本地代碼中已經(jīng)使用了實(shí)際的數(shù)據(jù)類型,等同于用實(shí)際類型寫的類,所以不同的封閉類的本地代碼是不一樣的。按照這個(gè)原理,我們可以這樣認(rèn)為:泛型類的不同的封閉類是分別不同的數(shù)據(jù)類型。

這樣泛型不僅更加靈活,也同時(shí)將代碼的簡(jiǎn)便和提高到一個(gè)層次!不用再為具體不同的重載方法寫具體的代碼了!

C# 泛型是開發(fā)工具庫中的一個(gè)無價(jià)之寶。它們可以提高性能、類型安全和質(zhì)量,減少重復(fù)性的編程任務(wù),簡(jiǎn)化總體編程模型,而這一切都是通過優(yōu)雅的、可讀性強(qiáng)的語法完成的。盡管 C# 泛型的根基是 C++ 模板,但 C# 通過提供編譯時(shí)安全和支持將泛型提高到了一個(gè)新水平。C# 利用了兩階段編譯、元數(shù)據(jù)以及諸如約束和一般方法之類的創(chuàng)新性的概念。毫無疑問,C# 的將來版本將繼續(xù)發(fā)展泛型,以便添加新的功能,并且將泛型擴(kuò)展到諸如數(shù)據(jù)訪問或本地化之類的其他 .NET Framework 領(lǐng)域。

當(dāng)然,C#的泛型還很多應(yīng)用,現(xiàn)在我還只是了解了它的機(jī)制和原理,在接下來的學(xué)習(xí)中我會(huì)系統(tǒng)得學(xué)習(xí)泛型所支持的抽象泛型,接口泛型,結(jié)構(gòu)和委托等!

【編輯推薦】

  1. 淺談C#如何實(shí)現(xiàn)多繼承
  2. C#語言與Java語言程序的比較
  3. 利用C#指針進(jìn)行圖像操作
  4. C#中用鼠標(biāo)移動(dòng)頁面功能的實(shí)現(xiàn)
  5. C#中實(shí)現(xiàn)多繼承的方式:混合+接口
責(zé)任編輯:彭凡 來源: cnblogs
相關(guān)推薦

2009-08-24 14:43:35

C# 泛型

2009-08-19 15:08:30

C#泛型

2009-08-26 09:36:03

C#泛型

2009-09-01 16:14:11

C#泛型

2009-08-24 10:29:39

C# 泛型

2013-03-20 09:27:33

C#泛型

2009-08-24 15:12:13

C# 泛型接口

2009-09-02 17:38:16

C#泛型支持

2009-08-24 18:15:24

C# Dictiona

2009-08-24 15:38:21

C# 泛型數(shù)組

2009-08-24 14:51:25

C# 泛型泛型類型

2009-08-24 14:20:13

C# 強(qiáng)制類型轉(zhuǎn)換

2009-08-24 10:07:57

C#泛型處理

2009-08-24 17:27:05

C#泛型應(yīng)用

2009-08-24 16:39:19

C# 泛型應(yīng)用

2009-08-24 17:58:19

C# 泛型集合

2009-08-26 18:02:05

C#泛型問題

2009-09-02 18:03:19

C#實(shí)現(xiàn)泛型類

2009-08-24 18:22:05

C# 泛型編程

2009-08-24 11:35:20

C# 泛型應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)