泛型

程序設計語言的風格之一

泛型程序設計(generic programming)是程序設計語言的一種風格或範式。泛型允許程序員在強類型程序設計語言中編寫代碼時使用一些以後才指定的類型,在實例化時作為參數指明這些類型。各種程序設計語言和其編譯器、運行環境對泛型的支持均不一樣。Ada、Delphi、Eiffel、Java、C#、F#、Swift 和 Visual Basic .NET 稱之為泛型(generics);ML、Scala 和 Haskell 稱之為參數多態(parametric polymorphism);C++ 和 D稱之為模板。具有廣泛影響的1994年版的《Design Patterns》一書稱之為參數化類型(parameterized type)。

定義分類


泛型義:
.程序編碼包含類型參類型,泛型參類,。(今較義)
.程序編碼包含參類。參類。(稱模板)論哪義,泛型參泛型必須指。
一些強類型編程語言支持泛型,其主要目的是加強類型安全及減少類轉換的次數,但一些支持泛型的編程語言只能達到部分目的。

編程語言


.NET Framework的泛型
泛型是具有佔位符(類型參數)的類、結構、介面和方法,這些佔位符是類、結構、介面和方法所存儲或使用的一個或多個類型的佔位符。泛型集合類可以將類型參數用作它所存儲的對象的類型的佔位符;類型參數作為其欄位的類型及其方法的參數類型出現。泛型方法可以將其類型參數用作其返回值的類型或者其某個形參的類型。
由於NET Framework泛型的類型參數之實際類型在運行時均不會被消除,運行速度會因為類型轉換的次數減少而加快。
另外,使用GetType方法可於程序運行時得知泛型及其類型參數的實際類型,更可以運用反射編程。
允許對個別泛型的類型參數進行約束,包括以下幾種形式(假設C是泛型的類型參數,是一般類、泛類,或是泛型的類型參數):T是一個類。T是一個值類型。T具有無參數的公有建構方法。T實現介面I。T是C,或繼承自C。
泛型約束
泛型約束
Java的泛型
Java泛型的參數只可以代表類,不能代表個別對象。由於Java泛型的類型參數之實際類型在編譯時會被消除,所以無法在運行時得知其類型參數的類型。Java編譯器在編譯泛型時會自動加入類型轉換的編碼,故運行速度不會因為使用泛型而加快。Java允許對個別泛型的類型參數進行約束,包括以下兩種形式(假設T是泛型的類型參數,C是一般類、泛類,或是泛型的類型參數):T實現介面I。T是C,或繼承自C。一個泛型類不能實現Throwable介面。
C++的泛型(模板)
C++無法對泛型的類型參數進行約束。在編譯時,每個被使用的封閉泛型類型(即是所有泛型參數的實際類型都已被指明的泛型)都會有獨立的編碼產生,編譯器會在此時確保類型安全性。可是如果泛型要運用其泛型參數的某成員,而該泛型參數又不包含該成員的時候,編譯器所產生的錯誤信息會看似與實際問題無關,增加除錯的難度。

好處


泛型是c#2.0的一個新增加的特性,它為使用c#語言編寫面向對象程序增加了極大的效力和靈活性。不會強行對值類型進行裝箱和拆箱,或對引用類型進行向下強制類型轉換,所以性能得到提高。通過知道使用泛型定義的變數的類型限制,編譯器可以在一個高得多的程度上驗證類型假設,所以泛型提高了程序的類型安全。它允許程序員將一個實際的數據類型的規約延遲至泛型的實例被創建時才確定。泛型為開發者提供了一種高性能的編程方式,能夠提高代碼的重用性,並允許開發者編寫非常優雅的解決方案。
泛型類和泛型方法同時具備可重用性、類型安全和效率,這是非泛型類和非泛型方法無法具備的。泛型通常用與集合以及作用於集合的方法一起使用。.NET Framework2.0版類庫提供一個新的命名空間 System.Collections.Generic,其中包含幾個新的基於泛型的集合類。建議面向2.0版的所有應用程序都使用新的泛型集合類,而不要使用舊的非泛型集合類,如ArrayList。有關更多信息,請參見.NET Framework類庫中的泛型(C#編程指南)。
當然,也可以創建自定義泛型類型和方法,以提供自己的通用解決方案,設計類型安全的高效模式。下面的代碼示例演示一個用於演示用途的簡單泛型鏈接列表類。(大多數情況下,應使用.NET Framework類庫提供的List<(Of <(T>)>)類,而不是自行創建類。)在通常使用具體類型來指示列表中存儲的項的類型的場合,可使用類型參數T。其使用方法如下:
在AddHead方法中作為方法參數的類型。
Node嵌套類中作為公共方法GetNext和Data屬性的返回類型。
在嵌套類中作為私有成員數據的類型。
注意,T可用於Node嵌套類。如果使用具體類型實例化GenericList(例如,作為GenericList),則所有的T都將被替換為int。
// type parameter T in angle bracketspublicclass public class GenericList { // 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 GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } }}
下面的代碼示例演示客戶端代碼如何使用泛型 GenericList 類來創建整數列表。只需更改類型參數,即可方便地修改下面的代碼示例,創建字元串或任何其他自定義類型的列表:
class TestGenericList{ static void Main() { // int is the type argument GenericList list = new GenericList(); for (int x = 0; x < 10; x++) { list.AddHead(x); } foreach (int i in list) { System.Console.Write(i + " "); } System.Console.WriteLine("\nDone"); } }