[译]聊聊C#中的泛型的使用
寫在前面
今天忙里偷閑在瀏覽外文的時(shí)候看到一篇講C#中泛型的使用的文章,因此加上本人的理解以及四級(jí)沒過的英語水平斗膽給大伙進(jìn)行了翻譯,當(dāng)然在翻譯的過程中發(fā)現(xiàn)了一些問題,因此也進(jìn)行了糾正,當(dāng)然,原文的地址我放在最下面,如果你的英文水平比較好的話,可以直接直接閱讀全文。同時(shí)最近建了一個(gè).NET Core實(shí)戰(zhàn)項(xiàng)目交流群637326624,有興趣的朋友可以來相互交流。目前.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS的教程也已經(jīng)更新了6篇了,目前兩到三天更新一篇。
作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/10029782.html
介紹
C#和.NET中的泛型程序具有強(qiáng)類型集合的許多優(yōu)點(diǎn),并為代碼提供更高質(zhì)量和性能提升。泛型是C#語言和公共語言運(yùn)行庫(kù)(CLR)中的一個(gè)新功能,它將類型參數(shù)的概念引入.NET Framework。類型參數(shù)使得設(shè)計(jì)某些類和方法成為可能,例如,通過使用泛型類型參數(shù)T,可以大大簡(jiǎn)化類型之間的強(qiáng)制轉(zhuǎn)換或裝箱操作的過程(裝箱、拆箱問題)。說白了,泛型就是通過參數(shù)化類型來實(shí)現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型,利用“參數(shù)化類型”將類型抽象化,從而實(shí)現(xiàn)靈活的復(fù)用。每個(gè)集合的詳細(xì)規(guī)范可以在System.Collection.Generic名稱空間下找到。
裝箱和拆箱
.Net定義了兩種主要的數(shù)據(jù)類型來表示變量,也就是傳說中的值類型和引用類型。這是需要裝箱和拆箱的地方。裝箱是一種通過將變量存儲(chǔ)到System.Object中來顯式地將值類型轉(zhuǎn)換為引用類型的機(jī)制。當(dāng)您裝入值時(shí),CLR會(huì)將新對(duì)象分配到堆中,并將值類型的值復(fù)制到該實(shí)例中。例如,您創(chuàng)建了一個(gè)int類型的變量:
int a = 20; ?object b = a; //裝箱相反的操作是拆箱,它是將引用類型轉(zhuǎn)換回值類型的過程。此過程驗(yàn)證接收數(shù)據(jù)類型是否與裝箱類型一致;
int c = (int)b; // 拆箱C#編譯器可以看到從int到object的賦值,反之亦然。當(dāng)編譯該程序并通過IL解析器檢查IL生成的代碼時(shí),您會(huì)注意到當(dāng)b被賦值為a時(shí),程序通過在IL中自動(dòng)插入一個(gè)box指令來響應(yīng),當(dāng)c被賦值為b時(shí)如下;
代碼加載常量20并將其存儲(chǔ)在本地插槽中;它將值20加載到堆棧中并將其裝箱。最后,它將被裝箱的20返回到堆棧上,并將其拆箱為int類型
這個(gè)過程.NET CLR執(zhí)行了一系列操作,例如,首先在托管堆中分配一個(gè)對(duì)象,然后在裝箱中將值轉(zhuǎn)換為內(nèi)存位置,并在拆箱期間將值存儲(chǔ)在堆上并且必須轉(zhuǎn)回到堆棧。因此,從性能的角度來看,裝箱和拆箱過程在泛型中具有非常重要的意義,因?yàn)檫@個(gè)過程如果不使用泛型的話會(huì)耗費(fèi)更多地資源。
泛型類
可以通過在類名后面加上符號(hào)來定義泛型類。這里沒有強(qiáng)制必須將“T”字放在泛型的定義中。您可以在TestClass <>類聲明中使用任何單詞。
public class TestClass<T> { } ?System.Collection.Generic命名空間下還定義了許多實(shí)現(xiàn)了這些關(guān)鍵字接口的類型。下表列出了此命名空間的核心類類型。
| Collection | 泛型集合的基類,可以比較兩個(gè)泛型對(duì)象是否相等 |
| Dictionary<TKey, TValue> | 鍵值對(duì)的泛型集合 |
| List | 可動(dòng)態(tài)調(diào)整列表項(xiàng)的大小 |
| Queue | 先進(jìn)先出(FIFO)列表的泛型實(shí)現(xiàn) |
| Stack | 后進(jìn)先出(LIFO)列表的泛型實(shí)現(xiàn) |
簡(jiǎn)單的泛型類示例
以下示例顯示了一個(gè)簡(jiǎn)單的泛型類型的操作。TestClass?定義一個(gè)長(zhǎng)度為5的泛型類型數(shù)組。Add()方法負(fù)責(zé)將任何類型的對(duì)象添加到集合中,而Indexer屬性是循環(huán)
在構(gòu)建并運(yùn)行該程序之后,程序的輸出如下所示;
泛型的主要特性
泛型類型的一些重要特征使它們相比傳統(tǒng)的非泛型類型具有如下的顯著特征:
類型安全
性能
二進(jìn)制代碼復(fù)用
類型安全
泛型最重要的特征之一是類型安全性。對(duì)于非泛型ArrayList類,如果使用對(duì)象類型,則可以向集合中添加任何類型,這些類型有時(shí)會(huì)導(dǎo)致嚴(yán)重的問題。下面的示例顯示向ArrayList類型的集合添加一個(gè)整數(shù)、字符串和對(duì)象;
ArrayList obj = new ArrayList(); ? obj.Add(50); ? obj.Add("Dog"); ? obj.Add(new TestClass()); ?現(xiàn)在,如果使用整數(shù)對(duì)象來使用foreach語句進(jìn)行遍歷的話,當(dāng)編譯器接受到代碼,但是因?yàn)榧现械乃性囟疾皇钦麛?shù),所以會(huì)導(dǎo)致運(yùn)行時(shí)異常;
foreach(int i in obj) ? { ?Console.WriteLine(i); ? ? } ?編程的經(jīng)驗(yàn)法則是應(yīng)該盡早檢測(cè)到錯(cuò)誤。對(duì)于泛型類Test,泛型類型T定義允許哪些類型。通過使用Test的定義,只能向集合添加整型類型的數(shù)據(jù)。這時(shí)候當(dāng)Add()方法具有以下無效參數(shù)的時(shí)候編譯器將不編譯代碼;
Test<int> obj = new Test<int>(); ? obj.Add(50); ? obj.Add("Dog"); ? ? ? ? ? ?//編譯錯(cuò)誤 obj.Add(new TestClass()); ?//編譯錯(cuò)誤性能
在下面的示例中,ArrayList類存儲(chǔ)對(duì)象,并且定義了Add()方法來存儲(chǔ)一些整型參數(shù)。因此,整數(shù)類型被裝箱。當(dāng)使用foreach語句讀取ArrayList中的值時(shí),將發(fā)生拆箱。
ArrayList ?obj = new ArrayList(); ? obj.Add(50); ? ?//裝箱- 值類型轉(zhuǎn)換成引用類型 int x= (int)obj[0]; //拆箱foreach(int i in obj) ? { ?Console.WriteLine(i); ? // 拆箱}
注意:泛型比其他集合(如ArrayList)更快。
代替使用對(duì)象類型,TestClass類的泛型類型被定義為int,因此在從編譯器動(dòng)態(tài)生成的類中將使用int類型。所以將不會(huì)發(fā)生裝箱和拆箱,如下所示;
TestClass<int> obj = new TestClass<int>(); ? obj.Add(50); ? ?//沒有裝箱int x= obj[0]; // 沒有拆箱
foreach(int i in obj) ? { ?Console.WriteLine(i); ? //沒有拆箱
} ?
二進(jìn)制代碼復(fù)用
泛型類型提供了一種源代碼保護(hù)機(jī)制。泛型類可以定義一次,并且可以使用許多不同類型來進(jìn)行實(shí)例化。泛型可以在一種CLR支持的語言中定義,并可以被另一種.NET語言使用。以下TestClass?使用int和string類型進(jìn)行實(shí)例化:
TestClass<int> obj = new TestClass<int>(); ? obj.Add(50); ?TestClass<string> obj1 = new TestClass<string>(); ? Obj1.Add("hello"); ?通用方法
雖然大多數(shù)開發(fā)人員通常會(huì)使用基類庫(kù)中的現(xiàn)有泛型類型,但也有可能會(huì)構(gòu)建自己的泛型成員和自定義的泛型類型。
本示例的目的是構(gòu)建一個(gè)交換方法,該方法可以使用單個(gè)類型參數(shù)對(duì)任何可能的數(shù)據(jù)類型(基于值或基于引用)進(jìn)行操作。由于交換算法的性質(zhì),傳入的參數(shù)將作為使用ref關(guān)鍵字修飾的引用類型來進(jìn)行發(fā)送。
編譯此泛型方法實(shí)現(xiàn)的程序后,輸出如下所示;
字典
字典也被稱為映射或散列表。它表示允許您基于關(guān)鍵字來訪問元素的數(shù)據(jù)結(jié)構(gòu)。字典的一個(gè)重要特征是更快的查找; 您可以添加或刪除選項(xiàng)而不會(huì)產(chǎn)生性能開銷。
.Net提供了幾個(gè)字典類,例如Dictionary <TKey,TValue>。類型參數(shù)TKey和TValue分別表示關(guān)鍵字的類型和它可以存儲(chǔ)的值。
簡(jiǎn)單的字典示例
以下示例演示使用泛型的簡(jiǎn)單字典集合。在此程序中,將創(chuàng)建一個(gè)Dictionary類型對(duì)象,該對(duì)象接受int作為鍵,字符串作為值。然后我們將一些字符串值添加到字典集合中,最后顯示字典集合元素。
以下示例通過定義附加類emp來描述一些更復(fù)雜的問題,其中我們覆蓋ToString()方法以顯示特定員工的名稱和薪水。稍后在Main()方法中,創(chuàng)建一個(gè)新的Dictionary <TKey,TValue)的實(shí)例,其中鍵的類型為string,值為emp類型。構(gòu)造函數(shù)分配2個(gè)元素的容量。emp對(duì)象和作為鍵的字符串值被添加到字典集合中。最后,使用foreach語句迭代集合元素并顯示在屏幕上。
隊(duì)列
隊(duì)列是一種特殊類型的容器,可確保以FIFO(先進(jìn)先出)方式訪問元素。隊(duì)列集合最適合實(shí)現(xiàn)消息傳遞的組件。我們可以使用以下語法定義Queue集合對(duì)象:
Queue qObj = new Queue();Queue集合的屬性,方法和其他規(guī)則定義都位于Sysyem.Collection命名空間下。下表定義了關(guān)鍵成員;
| Enqueue() | 將對(duì)象添加到隊(duì)列的末尾。 |
| Dequeue() | 從隊(duì)列的開頭刪除對(duì)象。 |
| Peek() | 返回隊(duì)列開頭的對(duì)象而不刪除它。 |
下面演示了一個(gè)基本的隊(duì)列類型的集合,將一些字符串類型值添加到集合中,最后使用while語句來顯示整個(gè)集合中的數(shù)據(jù) 。
堆棧
Stack集合是LIFO的抽象(后進(jìn)先出)。我們可以使用以下語法定義Stack集合對(duì)象:
Stack qObj = new Stack();下表說明了堆棧的關(guān)鍵成員;
| Contains() | 如果在集合中找到特定元素,則返回true。 |
| Clear() | 刪除集合的所有元素。 |
| Peek() | 預(yù)覽堆棧中的最新元素。 |
| Push() | 它將元素推入堆棧。 |
| Pop() | 返回并刪除堆棧的頂部元素。 |
以下演示了堆棧集合。首先,將數(shù)組類型對(duì)象引用到堆棧集合中。然后使用Pop()方法從堆棧中刪除集合中元素的值并顯示在屏幕上。
在使用泛型實(shí)現(xiàn)的另一個(gè)示例中,使用Push()方法將5個(gè)項(xiàng)添加到堆棧中。然后使用循環(huán)迭代輸出堆棧中的數(shù)據(jù)。堆棧的枚舉器不會(huì)刪除數(shù)據(jù); 它只是以LIFO方式返回每個(gè)項(xiàng)目,如下所示:
總結(jié)
今天忙里偷閑,在瀏覽外文的時(shí)候看到一篇講泛型的文章,因此就加上自己的理解進(jìn)行了相關(guān)翻譯,也加深了自己對(duì)泛型的理解!如果英文比較好的話可以直接訪問https://www.c-sharpcorner.com/UploadFile/84c85b/using-generics-with-C-Sharp/ 自行查看!當(dāng)然,我在翻譯的過程中也發(fā)現(xiàn)了文中的一些錯(cuò)誤,所以進(jìn)行了更正!同時(shí)最近建了一個(gè).NET Core實(shí)戰(zhàn)項(xiàng)目交流群637326624,有興趣的朋友可以來相互交流。目前.NET Core實(shí)戰(zhàn)項(xiàng)目之CMS的教程也已經(jīng)更新了6篇了,目前兩到三天更新一篇。最后感謝大家的閱讀。
原文地址:https://www.cnblogs.com/yilezhu/p/10029782.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的[译]聊聊C#中的泛型的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【.NET Core项目实战-统一认证平
- 下一篇: Docker最全教程——从理论到实战(三