C# 泛型應(yīng)用及優(yōu)點淺析
C# 泛型應(yīng)用的好處是什么呢?.NET 中的泛型使您可以重用代碼以及在實現(xiàn)它時付出的努力。類型和內(nèi)部數(shù)據(jù)可以在不導(dǎo)致代碼膨脹的情況下更改,而不管您使用的是值類型還是引用類型。您可以一次性地開發(fā)、測試和部署代碼,通過任何類型(包括將來的類型)來重用它,并且全部具有編譯器支持和類型安全。因為一般代碼不會強(qiáng)行對值類型進(jìn)行裝箱和取消裝箱,或者對引用類型進(jìn)行向下強(qiáng)制類型轉(zhuǎn)換,所以性能得到顯著提高。對于值類型,性能通常會提高 200%;對于引用類型,在訪問該類型時,可以預(yù)期性能最多提高 100%(當(dāng)然,整個應(yīng)用程序的性能可能會提高,也可能不會提高)。本文隨附的源代碼包含一個微型基準(zhǔn)應(yīng)用程序,它在緊密循環(huán)中執(zhí)行堆棧。該應(yīng)用程序使您可以在基于 Object 的堆棧和一般堆棧上試驗值類型和引用類型,以及更改循環(huán)迭代的次數(shù)以查看泛型對性能產(chǎn)生的影響。
C# 泛型應(yīng)用分析
因為 IL 和 CLR 為泛型提供本機(jī)支持,所以大多數(shù)符合 CLR 的語言都可以利用一般類型。例如,下面這段 Visual Basic .NET 代碼使用代碼塊 2 的一般堆棧:
- Dim stack As Stack(Of Integer)
- stack = new Stack(Of Integer)
- stack.Push(3)
- Dim number As Integer
- number = stack.Pop()
您可以在類和結(jié)構(gòu)中使用泛型。以下是一個有用的一般點結(jié)構(gòu):
- public struct Point
- {
- public T X;
- public T Y;
- }
可以使用該一般點來表示整數(shù)坐標(biāo),例如:
- Point point;
- point.X = 1;
- point.Y = 2;
或者,可以使用它來表示要求浮點精度的圖表坐標(biāo):
- Point point;
- point.X = 1.2;
- point.Y = 3.4;
除了到目前為止介紹的基本泛型語法以外,C# 2.0 還具有一些泛型特定的語法。例如,請考慮代碼塊 2 的 Pop() 方法。假設(shè)您不希望在堆棧為空時引發(fā)異常,而是希望返回堆棧中存儲的類型的默認(rèn)值。如果您使用基于 Object 的堆棧,則可以簡單地返回 null,但是您還可以通過值類型來使用一般堆棧。為了解決該問題,您可以使用 default() 運算符,它返回類型的默認(rèn)值。
下面說明如何在 Pop() 方法的實現(xiàn)中使用默認(rèn)值:
- public T Pop()
- {
- m_StackPointer--;
- if(m_StackPointer >= 0)
- {
- return m_Items[m_StackPointer];
- }
- else
- {
- m_StackPointer = 0;
- return default(T);
- }
- }
引用類型的默認(rèn)值為 null,而值類型(例如,整型、枚舉和結(jié)構(gòu))的默認(rèn)值為全零(用零填充相應(yīng)的結(jié)構(gòu))。因此,如果堆棧是用字符串構(gòu)建的,則 Pop() 方法在堆棧為空時返回 null;如果堆棧是用整數(shù)構(gòu)建的,則 Pop() 方法在堆棧為空時返回零。
C# 泛型應(yīng)用之多個一般類型
單個類型可以定義多個一般類型參數(shù)。例如,請考慮代碼塊 3 中顯示的一般鏈表。
C# 泛型應(yīng)用代碼塊之一般鏈表
- class Node
- {
- public K Key;
- public T Item;
- public Node NextNode;
- public Node()
- {
- Key = default(K);
- Item = defualt(T);
- NextNode = null;
- }
- public Node(K key,T item,Node nextNode)
- {
- Key = key;
- Item = item;
- NextNode = nextNode;
- }
- }
- public class LinkedList
- {
- Node m_Head;
- public LinkedList()
- {
- m_Head = new Node();
- }
- public void AddHead(K key,T item)
- {
- Node newNode = new Node(key,item,m_Head.NextNode);
- m_Head.NextNode = newNode;
- }
- }
該鏈表存儲節(jié)點:
- class Node
- {...}
每個節(jié)點都包含一個鍵(屬于一般類型參數(shù) K)和一個值(屬于一般類型參數(shù) T)。每個節(jié)點還具有對該列表中下一個節(jié)點的引用。鏈表本身根據(jù)一般類型參數(shù) K 和 T 進(jìn)行定義:
- public class LinkedList
- {...}
這使該列表可以公開像 AddHead() 一樣的一般方法:
- public void AddHead(K key,T item);
每當(dāng)您聲明使用泛型的類型的變量時,都必須指定要使用的類型。但是,指定的類型實參本身可以為一般類型參數(shù)。例如,該鏈表具有一個名為 m_Head 的 Node 類型的成員變量,用于引用該列表中的第一個項。m_Head 是使用該列表自己的一般類型參數(shù) K 和 T 聲明的。
- Node m_Head;
您需要在實例化節(jié)點時提供類型實參;同樣,您可以使用該鏈表自己的一般類型參數(shù):
- public void AddHead(K key,T item)
- {
- Node newNode = new Node<K,T>(key,item,m_Head.NextNode);
- m_Head.NextNode = newNode;
- }
請注意,該列表使用與節(jié)點相同的名稱來表示一般類型參數(shù)完全是為了提高可讀性;它也可以使用其他名稱,例如:
- public class LinkedList
- {...}
或:
- public class LinkedList
- {...}
在這種情況下,將 m_Head 聲明為:
- Node m_Head;
當(dāng)客戶端使用該鏈表時,該客戶端必須提供類型實參。該客戶端可以選擇整數(shù)作為鍵,并且選擇字符串作為數(shù)據(jù)項:
- LinkedList list = new LinkedList();
- list.AddHead(123,"AAA");
但是,該客戶端可以選擇其他任何組合(例如,時間戳)來表示鍵:
- LinkedList list = new LinkedList();
- list.AddHead(DateTime.Now,"AAA");
有時,為特定類型的特殊組合起別名是有用的。可以通過 using 語句完成該操作,如代碼塊 4 中所示。請注意,別名的作用范圍是文件的作用范圍,因此您必須按照與使用 using 命名空間相同的方式,在項目文件中反復(fù)起別名。
C# 泛型應(yīng)用代碼塊之 一般類型別名
- using List = LinkedList;
- class ListClient
- {
- static void Main(string[] args)
- {
- List list = new List();
- list.AddHead(123,"AAA");
- }
- }
C# 泛型應(yīng)用及C# 泛型應(yīng)用的優(yōu)點就向你介紹到這里,希望對你了解和學(xué)習(xí)C# 泛型應(yīng)用有所幫助。
【編輯推薦】