.NET Framework 中的泛型
泛型可讓您修正方法、類別、結構或是其運作所在的精確資料型別的介面。 例如,您可使用 Dictionary<TKey, TValue> 泛型類別以及指定索引鍵允許的型別和值允許的型別,而不要使用允許任何型別之索引鍵和值的 Hashtable 類別。 使用泛型的優點包括了增加程式碼的重複使用性和型別安全。
本主題將提供 .NET Framework 中泛型的概觀,以及泛型型別或方法的摘要。 它包含以下各節:
定義和使用泛型
泛型術語
類別庫和語言支援
巢狀型別和泛型
相關主題
參考資料
定義和使用泛型
泛型是指一些類別、結構、介面和方法,而它們具有其儲存或使用的一個或多個型別之替代符號 (型別參數)。 泛型集合類別可能會將型別參數當做它所儲存的物件型別之替代符號;這些型別參數會以其欄位型別及其方法的參數型別之形式出現。 泛型方法可能會將它的型別參數當做其傳回值的型別或是其中一個正規參數的型別使用。 下列程式碼將說明簡單的泛型類別定義。
Public Class Generic(Of T)
Public Field As T
End Class
public class Generic<T>
{
public T Field;
}
generic<typename T>
public ref class Generics
{
public:
T Field;
};
當您建立泛型類別的執行個體時,您要指定實際型別來替代型別參數, 如此將會建立新的泛型類別 (稱為建構的泛型類別),而您選擇的型別會替代型別參數出現的任何地方。 產生的結果是適合您選擇的型別之型別安全類別,如下列程式碼所說明。
Public Shared Sub Main()
Dim g As New Generic(Of String)
g.Field = "A string"
'...
Console.WriteLine("Generic.Field = ""{0}""", g.Field)
Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub
public static void Main()
{
Generic<string> g = new Generic<string>();
g.Field = "A string";
//...
Console.WriteLine("Generic.Field = \"{0}\"", g.Field);
Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}
static void Main()
{
Generics<String^>^ g = gcnew Generics<String^>();
g->Field = "A string";
//...
Console::WriteLine("Generics.Field = \"{0}\"", g->Field);
Console::WriteLine("Generics.Field.GetType() = {0}", g->Field->GetType()->FullName);
}
回到頁首
泛型術語
下列詞彙是用來討論有關 .NET Framework 中的泛型:
「泛型型別定義」(Generic Type Definition) 是當做樣板使用的類別、結構或介面宣告,且具有它可以包含或使用的型別之替代符號。 例如,System.Collections.Generic.Dictionary<TKey, TValue> 類別可包含兩種型別:索引鍵和值。 因為泛型型別定義只是樣板,所以您無法為本身是泛型型別定義的類別、結構或介面建立執行個體。
「泛型型別參數」(Generic Type Parameter) 或「型別參數」(Type Parameter) 為泛型型別或方法定義中的替代符號。 System.Collections.Generic.Dictionary<TKey, TValue> 泛型型別有兩個型別參數:TKey 和 TValue,表示它的索引鍵和值的型別。
「建構的泛型型別」(Constructed Generic Type) 或「建構的型別」(Constructed Type) 為針對泛型型別定義的泛型型別參數指定型別的結果。
「泛型型別引數」(Generic Type Argument) 為用來替代泛型型別參數的任何型別。
「泛型型別」(Generic Type) 一詞通常包括建構的型別和泛型型別定義。
泛型型別參數的「共變性」(Covariance) 和「逆變性」(Contravariance) 可讓您使用建構的泛型型別,其型別引數的衍生程度比目標建構的型別更高 (共變性) 或更低 (逆變性)。 共變性和逆變性合稱為「變異性」(Variance)。 如需詳細資訊,請參閱 泛型中的共變數和反變數。
「條件約束」(Constraint) 是對泛型型別參數所設的限制。 例如,您可以將型別參數限制為實作 System.Collections.Generic.IComparer<T> 泛型介面的型別,以確保此型別的執行個體可以排序。 您也可以將型別參數限制為具有特定基底類別、具有預設建構函式或為參考型別或實值型別等型別。 使用此泛型型別時不能以不滿足這些條件約束的型別引數來替代。
「泛型方法定義」(Generic Method Definition) 是具有兩個參數清單的方法:泛型型別參數的清單和型式參數的清單。 型別參數可以傳回型別或型式參數的型別之形式出現,如下列程式碼所示。
Function Generic(Of T)(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function
T Generic<T>(T arg)
{
T temp = arg;
//...
return temp;
}
generic<typename T>
T Generic(T arg)
{
T temp = arg;
//...
return temp;
}
泛型方法可以出現在泛型或非泛型型別上。 很重要的一點是,方法不會只是因為屬於泛型型別,或甚至因為它的正規參數之型別為封入型別的泛型參數,就屬於泛型; 只有當方法擁有它自己的型別參數清單時,才會是泛型。 在下列程式碼中,只有方法 G 是泛型。
Class A
Function G(Of T)(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function
End Class
Class Generic(Of T)
Function M(ByVal arg As T) As T
Dim temp As T = arg
'...
Return temp
End Function
End Class
class A
{
T G<T>(T arg)
{
T temp = arg;
//...
return temp;
}
}
class Generic<T>
{
T M(T arg)
{
T temp = arg;
//...
return temp;
}
}
ref class A
{
generic<typename T>
T G(T arg)
{
T temp = arg;
//...
return temp;
}
};
generic<typename T>
ref class Generic
{
T M(T arg)
{
T temp = arg;
//...
return temp;
}
};
回到頁首
類別庫和語言支援
.NET Framework 以下列命名空間提供一些泛型集合類別:
System.Collections.Generic 命名空間收錄 .NET Framework 所提供的大多數泛型集合型別,例如 List<T> 和 Dictionary<TKey, TValue> 泛型類別。
System.Collections.ObjectModel 命名空間收錄其他泛型型別,例如 ReadOnlyCollection<T> 泛型類別,這些型別很適合用於將物件模型公開給您類別的使用者。
System 命名空間中提供用於實作排序和相等比較的泛型介面,也提供事件處理常式、轉換和搜尋述詞的泛型委派型別。
System.Reflection 命名空間中已加入的泛型支援可檢查泛型型別和泛型方法,System.Reflection.Emit 中已加入的泛型支援可發出包含泛型型別和方法的動態組件,而 System.CodeDom 中已加入的泛型支援可產生包含泛型的來源圖形。
Common Language Runtime 提供新的 opcode 和前置詞來支援 Microsoft Intermediate Language (MSIL) 中的泛型型別,包括 Stelem、Ldelem、Unbox_Any、Constrained 和 Readonly。
Visual C++、C# 和 Visual Basic 對泛型的定義和使用都有提供完整的支援。 如需語言支援的詳細資訊,請參閱 Visual Basic 中的泛型型別 (Visual Basic)、泛型簡介 (C# 程式設計手冊) 和 Overview of Generics in Visual C++。
回到頁首
巢狀型別和泛型
泛型型別中的巢狀型別可能依據封入泛型型別的型別參數而定。 Common Language Runtime 會將巢狀型別視為泛型,即使這些型別本身沒有泛型型別參數。 當您建立巢狀型別的執行個體時,必須要為所有封入泛型型別指定型別引數。
回到頁首
相關主題
標題 |
說明 |
---|---|
描述 .NET Framework 中的泛型集合類別和其他泛型型別。 |
|
描述轉換、搜尋述詞以及在陣列或集合元素上要採取的動作之泛型委派。 |
|
描述提供跨泛型型別系列的通用功能之泛型介面。 |
|
描述泛型型別參數中的共變性和逆變性。 |
|
摘要說明使用泛型的優點和限制。 |
|
提供與 .NET Framework 中之集合型別 (包括泛型型別) 的特性和使用情節有關的摘要資訊。 |
|
描述用來判斷何時使用泛型集合型別的一般規則。 |
|
說明如何產生動態組件,包括泛型型別和方法。 |
|
描述 Visual Basic 使用者的泛型功能,包括使用及定義泛型型別的 HOW TO 主題。 |
|
提供針對 C# 使用者定義及使用泛型型別的概觀。 |
|
描述 C++ 使用者的泛型功能,包括泛型和樣板之間的差異。 |
回到頁首
參考資料
System.Collections.ObjectModel
System.Reflection.Emit.OpCodes
回到頁首