詳解C#中的泛型以及編程中使用泛型的優(yōu)點(diǎn)
2.0 版 C# 語言和公共語言運(yùn)行時(shí) (CLR) 中增加了泛型。泛型將類型參數(shù)的概念引入 .NET Framework,類型參數(shù)使得設(shè)計(jì)如下類和方法成為可能:這些類和方法將一個(gè)或多個(gè)類型的指定推遲到客戶端代碼聲明并實(shí)例化該類或方法的時(shí)候。例如,通過使用泛型類型參數(shù) T,您可以編寫其他客戶端代碼能夠使用的單個(gè)類,而不致引入運(yùn)行時(shí)強(qiáng)制轉(zhuǎn)換或裝箱操作的成本或風(fēng)險(xiǎn),如下所示:
// Declare the generic class. public class GenericList<T> { void Add(T input) { } } class TestGenericList { private class ExampleClass { } static void Main() { // Declare a list of type int. GenericList<int> list1 = new GenericList<int>(); // Declare a list of type string. GenericList<string> list2 = new GenericList<string>(); // Declare a list of type ExampleClass. GenericList<ExampleClass> list3 = new GenericList<ExampleClass>(); } }
泛型概述
使用泛型類型可以最大限度地重用代碼、保護(hù)類型的安全以及提高性能。
泛型最常見的用途是創(chuàng)建集合類。
.NET Framework 類庫在 System.Collections.Generic 命名空間中包含幾個(gè)新的泛型集合類。應(yīng)盡可能地使用這些類來代替普通的類,如 System.Collections 命名空間中的 ArrayList。
您可以創(chuàng)建自己的泛型接口、泛型類、泛型方法、泛型事件和泛型委托。
可以對泛型類進(jìn)行約束以訪問特定數(shù)據(jù)類型的方法。
關(guān)于泛型數(shù)據(jù)類型中使用的類型的信息可在運(yùn)行時(shí)通過使用反射獲取。
泛型類和泛型方法同時(shí)具備可重用性、類型安全和效率,這是非泛型類和非泛型方法無法具備的。泛型通常用與集合以及作用于集合的方法一起使用。.NET Framework 2.0 版類庫提供一個(gè)新的命名空間 System.Collections.Generic,其中包含幾個(gè)新的基于泛型的集合類。建議面向 .NET Framework 2.0 及更高版本的所有應(yīng)用程序都使用新的泛型集合類,而不要使用舊的非泛型集合類如 ArrayList。
當(dāng)然,也可以創(chuàng)建自定義泛型類型和方法,以提供自己的通用解決方案,設(shè)計(jì)類型安全的高效模式。下面的代碼示例演示一個(gè)用于演示用途的簡單泛型鏈接列表類。(大多數(shù)情況下,應(yīng)使用 .NET Framework 類庫提供的 List<T> 類,而不是自行創(chuàng)建類。)在通常使用具體類型來指示列表中存儲的項(xiàng)的類型的場合,可使用類型參數(shù) T。其使用方法如下:
在 AddHead 方法中作為方法參數(shù)的類型。
在 Node 嵌套類中作為公共方法 GetNext 和 Data 屬性的返回類型。
在嵌套類中作為私有成員數(shù)據(jù)的類型。
注意,T 可用于 Node 嵌套類。如果使用具體類型實(shí)例化 GenericList<T>(例如,作為 GenericList<int>),則所有的 T 都將被替換為 int。
// type parameter T in angle brackets public class GenericList<T> { // The nested class is also generic on T. private class Node { // T used in non-generic constructor. public Node(T t) { next = null; data = t; } private Node next; public Node Next { get { return next; } set { next = value; } } // T as private member data type. private T data; // T as return type of property. public T Data { get { return data; } set { data = value; } } } private Node head; // constructor public GenericList() { head = null; } // T as method parameter type: public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } } }
下面的代碼示例演示客戶端代碼如何使用泛型 GenericList<T> 類來創(chuàng)建整數(shù)列表。只需更改類型參數(shù),即可方便地修改下面的代碼示例,創(chuàng)建字符串或任何其他自定義類型的列表:
class TestGenericList { static void Main() { // int is the type argument GenericList<int> list = new GenericList<int>(); for (int x = 0; x < 10; x++) { list.AddHead(x); } foreach (int i in list) { System.Console.Write(i + " "); } System.Console.WriteLine("\nDone"); } }
泛型的優(yōu)點(diǎn)
在公共語言運(yùn)行時(shí)和 C# 語言的早期版本中,通用化是通過在類型與通用基類型 Object 之間進(jìn)行強(qiáng)制轉(zhuǎn)換來實(shí)現(xiàn)的,泛型提供了針對這種限制的解決方案。通過創(chuàng)建泛型類,您可以創(chuàng)建一個(gè)在編譯時(shí)類型安全的集合。
使用非泛型集合類的限制可以通過編寫一小段程序來演示,該程序使用 .NET Framework 類庫中的 ArrayList 集合類。 ArrayList 是一個(gè)使用起來非常方便的集合類,無需進(jìn)行修改即可用來存儲任何引用或值類型。
// The .NET Framework 1.1 way to create a list: System.Collections.ArrayList list1 = new System.Collections.ArrayList(); list1.Add(3); list1.Add(105); System.Collections.ArrayList list2 = new System.Collections.ArrayList(); list2.Add("It is raining in Redmond."); list2.Add("It is snowing in the mountains.");
但這種方便是需要付出代價(jià)的。添加到 ArrayList 中的任何引用或值類型都將隱式地向上強(qiáng)制轉(zhuǎn)換為 Object。如果項(xiàng)是值類型,則必須在將其添加到列表中時(shí)進(jìn)行裝箱操作,在檢索時(shí)進(jìn)行取消裝箱操作。強(qiáng)制轉(zhuǎn)換以及裝箱和取消裝箱操作都會降低性能;在必須對大型集合進(jìn)行循環(huán)訪問的情況下,裝箱和取消裝箱的影響非常明顯。
另一個(gè)限制是缺少編譯時(shí)類型檢查;因?yàn)?ArrayList 會將所有項(xiàng)都強(qiáng)制轉(zhuǎn)換為 Object,所以在編譯時(shí)無法防止客戶端代碼執(zhí)行類似如下的操作:
System.Collections.ArrayList list = new System.Collections.ArrayList(); // Add an integer to the list. list.Add(3); // Add a string to the list. This will compile, but may cause an error later. list.Add("It is raining in Redmond."); int t = 0; // This causes an InvalidCastException to be returned. foreach (int x in list) { t += x; }
盡管將字符串和 ints 組合在一個(gè) ArrayList 中的做法在創(chuàng)建異類集合時(shí)是完全可接受的,并且有時(shí)需要有意為之,但這種做法很可能產(chǎn)生編程錯誤,并且直到運(yùn)行時(shí)才能檢測到此錯誤。
在 C# 語言的 1.0 和 1.1 版本中,只能通過編寫自己的特定于類型的集合來避免 .NET Framework 基類庫集合類中的通用代碼的危險(xiǎn)。當(dāng)然,由于此類不可對多個(gè)數(shù)據(jù)類型重用,因此將喪失通用化的優(yōu)點(diǎn),并且您必須對要存儲的每個(gè)類型重新編寫該類。
ArrayList 和其他相似類真正需要的是:客戶端代碼基于每個(gè)實(shí)例指定這些類要使用的具體數(shù)據(jù)類型的方式。這樣將不再需要向上強(qiáng)制轉(zhuǎn)換為 T:System.Object,同時(shí),也使得編譯器可以進(jìn)行類型檢查。換句話說,ArrayList 需要一個(gè)類型參數(shù)。這正是泛型所能提供的。在 N:System.Collections.Generic 命名空間的泛型 List<T> 集合中,向集合添加項(xiàng)的操作類似于以下形式:
// The .NET Framework 2.0 way to create a list List<int> list1 = new List<int>(); // No boxing, no casting: list1.Add(3); // Compile-time error: // list1.Add("It is raining in Redmond.");
對于客戶端代碼,與 ArrayList 相比,使用 List<T> 時(shí)添加的唯一語法是聲明和實(shí)例化中的類型參數(shù)。雖然這種方式稍微增加了編碼的復(fù)雜性,但好處是您可以創(chuàng)建一個(gè)比 ArrayList 更安全并且速度更快的列表,對于列表項(xiàng)是值類型的情況尤為如此。
上一篇:C#提取網(wǎng)頁中超鏈接link和text部分的方法
欄 目:C#教程
下一篇:使用C#編寫簡單的圖形化的可發(fā)送附件的郵件客戶端程序
本文標(biāo)題:詳解C#中的泛型以及編程中使用泛型的優(yōu)點(diǎn)
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6726.html
您可能感興趣的文章
- 01-10C#中查找Dictionary中的重復(fù)值的方法
- 01-10C#將圖片存放到SQL SERVER數(shù)據(jù)庫中的方法
- 01-10C#中Socket通信用法實(shí)例詳解
- 01-10關(guān)于nancy中的身份驗(yàn)證
- 01-10C#中的事務(wù)用法實(shí)例分析
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#類的多態(tài)性詳解
- 01-10C#創(chuàng)建不規(guī)則窗體的4種方式詳解
- 01-10C#實(shí)現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法
- 01-10C#中深度復(fù)制和淺度復(fù)制詳解


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 04-02jquery與jsp,用jquery
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改