Visual Basic 中的泛型類型 (Visual Basic)
泛型型別 是一個單一的程式元素,能適應多種資料類型執行相同的功能。 當您定義泛型類別或程式時,不需要針對您可能想要執行該功能的每個數據類型定義個別版本。
類比比喻是一個具有可拆卸頭部的螺絲起子套裝。 您檢查螺絲,並選擇適合該螺絲的一字、十字或星型螺絲頭。 一旦您將正確的螺絲起子頭插入螺絲起子握柄後,您就可以使用螺絲起子來旋轉螺絲。
當您定義泛型類型時,您可以使用一或多個資料類型將其參數化。 類型參數可讓程式代碼根據其需求量身打造數據類型。 您的程式碼可以從泛型元素宣告數個不同的程式元素,每個都作用於不同的數據型別集上。 但是,宣告的元素都會執行相同的邏輯,無論它們所使用的數據類型為何。
例如,您可能要建立和使用在特定資料類型上運作的佇列類別,例如 String
。 您可以從 System.Collections.Generic.Queue<T>宣告這類類別,如下列範例所示。
Public stringQ As New System.Collections.Generic.Queue(Of String)
您現在可以使用 stringQ
,以獨佔方式處理 String
值。 由於 stringQ
是 String
特定的,而不是針對 Object
值進行一般化,因此您沒有晚期系結或類型轉換。 泛型類型可節省運行時間,並減少運行時錯誤。
如需使用泛型型別的詳細資訊,請參閱 如何:使用泛型類別。
泛型類別的範例
下列範例顯示泛型類別的基本架構定義。
Public Class classHolder(Of t)
Public Sub processNewItem(ByVal newItem As t)
Dim tempItem As t
' Insert code that processes an item of data type t.
End Sub
End Class
在上述基本架構中,t
是 類型參數,也就是宣告類別時所提供數據類型的佔位元。 在程式代碼的其他地方,您可以藉由為 t
提供各種數據類型來宣告各種版本的 classHolder
。 下列範例顯示兩個這類宣告。
Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)
上述語句會宣告 建構類別,其中特定型別會取代類型參數。 此取代會在建構類別內的整個程式代碼中傳播。 下列範例顯示 integerClass
中 processNewItem
程式的外觀。
Public Sub processNewItem(ByVal newItem As Integer)
Dim tempItem As Integer
' Inserted code now processes an Integer item.
End Sub
如需更完整的範例,請參閱 如何:定義可在不同資料類型上提供相同功能的類別。
合格的程式設計元素
您可以定義和使用泛型類別、結構、介面、程式和委派。 .NET 定義數個泛型類別、結構和介面,這些類別代表常用的泛型專案。 System.Collections.Generic 命名空間提供字典、清單、佇列和堆疊。 在定義您自己的泛型元素之前,請查看 System.Collections.Generic中是否已提供該元素。
程式不是類型,但您可以定義和使用泛型程式。 請參閱 Visual Basic 中的泛型程式。
泛型類型的優點
泛型型別用作宣告數個不同程式元件的基礎,每個元件都在特定資料類型上運作。 泛型類型的替代方法是:
- 在
Object
數據類型上運行的單一類型。 - 一組 型類特定的 型類版本。 每個版本都會個別編碼,並在一個特定的數據類型上運作,例如
String
、Integer
或使用者定義型別,例如customer
。
泛型型別在這些替代方法上具有下列優點:
- 類型安全。 泛型類型會強制執行編譯時間類型檢查。 基於
Object
的類型可以接受任何資料類型,因此您必須撰寫程式碼來檢查輸入的資料類型是否可接受。 使用泛型類型,編譯程式可以在運行時間之前攔截類型不符。 - 性能。 泛型類型不需要 box 和 unbox 數據,因為每個類型都是針對單一數據類型特製化。 以
Object
為基礎的作業必須將輸入資料類型封裝成Object
,並將輸出資料解封。 Boxing 和 unboxing 可降低效能。 根據Object
的類型也是晚期綁定,這表示在運行時間存取其成員需要額外的程序代碼。 類型轉換也會降低效能。 - 程式碼整合。 泛型型別中的程式代碼必須只定義一次。 一組類型的特定類型版本必須在每個版本中複寫相同的程式代碼,唯一的差異在於該版本的特定數據類型。 使用泛型類型時,類型特定的版本全都是從原始泛型類型產生。
- 程式碼重用。 如果特定數據類型為泛型,則不相依於特定數據類型的程式代碼可以重複使用於各種數據類型。 即使是未預料到的數據類型,您也通常可以重複使用它。
- IDE 支援。 當您使用從泛型類型宣告的建構型別時,集成開發環境 (IDE) 可以在開發程式代碼時提供更多支援。 例如,IntelliSense 可以為您顯示建構函式或方法之自變數的類型特定選項。
- 泛型演算法。 與類型無關的抽象演算法是泛型型別的良好候選專案。 例如,使用 IComparable 介面排序項目的泛型程序可以搭配任何實作 IComparable的資料類型使用。
約束
雖然泛型類型定義中的程式代碼應該盡可能與類型無關,但您可能需要需要提供給泛型類型的任何數據類型的特定功能。 例如,如果您想要比較兩個項目來排序或整理,其數據類型必須實作 IComparable 介面。 您可以將 條件約束 新增至類型參數,以強制執行這項需求。
條件約束的範例
以下範例顯示一個類別的概要定義,包含一個條件約束,要求型別參數實作 IComparable。
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
如果後續程式代碼嘗試從提供未實作 IComparable的類型 itemManager
建構類別,編譯程式會發出錯誤訊號。
條件約束的類型
您的約束條件可以在任何組合中指定下列需求:
- 類型自變數必須實作一或多個介面
- 型別自變數必須是至多一個類別的類型或繼承自該類別。
- 類型自變數必須公開可從其中建立物件的程式代碼可存取的無參數建構函式
- 類型自變數必須是 參考型別,或者必須是 實值型別
C# 程式代碼可以宣告類型自變數必須是 Unmanaged 類型。 Visual Basic 會針對使用這個條件約束定義的泛型型別或方法的 Visual Basic 程式代碼強制執行這個條件約束(在 C# 中)。 不過,您無法在 Visual Basic 中的類型參數上宣告 unmanaged
條件約束。
如果您需要強加多個需求,請使用以逗號分隔的 條件約束清單, 放在大括號中 ({ }
)。 若要要求可存取的建構函式,請在清單中包含 New Operator 關鍵詞。 若要要求參考類型,請包含 Class
關鍵詞;若要要求實值類型,請包含 Structure
關鍵詞。
如需條件約束的詳細資訊,請參閱 類型清單。
多個條件約束的範例
下列範例顯示泛型類別的基本架構定義,其中包含類型參數的條件約束清單。 在建立這個類別實例的程式代碼中,型別自變數必須同時實作 IComparable 和 IDisposable 介面、做為參考型別,並公開可存取的無參數建構函式。
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
重要詞彙
泛型類型引進並使用下列詞彙:
- 泛型類型。 當您宣告類別、結構、介面、程式或委派時,需要提供至少一個數據類型的定義。
- 型態參數。 在泛型類型定義中,當您宣告類型時,您提供的數據類型的佔位符。
- 類型自變數。 當您從泛型型別宣告具體化型別時,用以取代型別參數的特定資料類型。
- 約束條件。 類型參數的條件,會限制您可以為其提供的類型自變數。 條件約束可以要求類型自變數實作特定介面、繼承自特定類別、具有可存取的無參數建構函式,或是參考型別或實值型別。 您可以結合這些條件約束,但最多可以指定一個基類。
- 構造類型。 從泛型類型提供類型引數以宣告類別、結構、介面、程序或委派。