共用方式為


Visual C++ 中的泛型概觀

泛型是指一些Common Language Runtime所支援的參數型型別。 參數化型別是定義使用泛型時指定了未知的型別參數的型別。

為什麼泛型嗎?

C + + 支援樣板和樣板和泛型同時支援參數化型別來建立型別集合類別。 不過,範本提供編譯-時間參數化。 您不能參考組譯碼包含範本定義和建立之範本的新特製化。 一旦編譯後,特定的範本看起來就像任何其他類別或方法。 泛型相較之下,在 MSIL 中發出為參數化型別已知的執行階段為參數化型別中。 來源參考組譯碼包含的泛型型別的程式碼可以建立的特製化的泛型型別。 如需有關比較 Visual C++ 樣板和泛型的請參閱泛型和樣板 (Visual C++)

泛用的函式和型別

類別型別,只要它們是Managed的型別,可能會是泛型。 舉例而言,這可能是List類別。 清單中之物件的型別會是型別參數。 如果您需要List類別為許多不同類型的物件之前可能使用的泛型, List採用 System::Object 做為項目類型。 但是,這可讓任何物件(包括錯誤型別的物件),在清單中使用。 不具型別的集合類別,會呼叫這類清單。 最佳情況下,您無法檢查在執行階段型別,並擲回例外狀況。 或者,您可能會使用範本時,就會遺失其泛用一次編譯成組譯碼的品質。 您的組譯碼的消費者可以建立自己的範本的特製化。 泛型能讓您建立假設型別集合類別, List<int> (作為"Int 的清單"讀取) 和 List<double> ("的清單雙") 這會產生編譯-錯誤如果您嘗試將型別集合不是設計成接受插入具型別集合。 此外,這些型別泛型後仍會保留在編譯。

描述泛型類別的語法可能會出現在泛型類別 (C++/CLI). 新命名空間, System.Collections.Generic,提出一組參數化的集合型別,包括Dictionary<TKey, TValue>List<T>LinkedList<T>。 如需詳細資訊,請參閱 .NET Framework 類別庫中的泛型 (C# 程式設計手冊)

執行個體和靜態類別成員函式、 委派和全域函式也可以是泛型。 如果此函式的參數都是未知的型別或函式本身必須使用泛用型別,泛型函式可能有必要。 在許多情況下, System::Object 可能已被用做為參數之未知的物件型別的過去,泛型型別參數可以用於相反地,可以有多個型別安全程式碼。 任何嘗試將傳入的型別,函式不是為了會標示為錯誤,在編譯時期。 使用 System::Object 做為函式參數,不小心的方式傳遞物件的函式並不為了處理將不會偵測,而且您必須將未知的物件型別,為特定型別轉換函式主體,並說明 InvalidCastException 的可能性。 使用泛型,嘗試將物件傳遞給函式的程式碼會導致型別衝突,因此保證函式主體都能正確的型別。

對相同好處套用建立在泛型集合類別。 在過去的集合類別會使用 System::Object ,將儲存集合的項目。 插入的集合不是為了型別的物件已不標幟在編譯階段,並且通常插入物件時,即使。 通常,物件會轉換成其他型別時就已存取集合中。 只有在型別轉換失敗時,才會發生未預期的型別才能偵測到。 泛型解決此問題在編譯階段偵測任何程式碼中插入的不相符的型別 (或隱含地轉換) 型別參數的泛型集合。

如需語法的說明,請參閱泛型函式 (C++/CLI)

有了泛型的術語

c570k3f3.collapse_all(zh-tw,VS.110).gif型別參數

泛型宣告包含一或多個未知的型別稱為型別參數。 型別參數是給予它代表泛型宣告的主體內的型別名稱。 型別參數用做為泛型宣告主體內的型別。 泛型宣告,如清單 <T> 包含型別參數t。

c570k3f3.collapse_all(zh-tw,VS.110).gif型別引數

型別引數是用來取代型別參數的泛型專門用於特定的型別或型別時的實際型別。 例如, int是型別引數,在List<int>。 實值型別和控制代碼的型別是以泛型型別引數中所允許的唯一型別。

c570k3f3.collapse_all(zh-tw,VS.110).gif建構的型別

從泛型型別建構的型別就是建構的型別。 未完整指定型別,例如List<T>是開啟建構的型別。 完整指定型別,例如List<double>,是封閉式建構型別特製化型別。 開放式建構型別不得使用於其他泛型型別或方法的定義,並不能完全指定直到封入泛型本身就是指定。 例如,以下是用於開啟建構的型別為基底類別泛型:

// generics_overview.cpp

// compile with: /clr /c

generic <typename T>

ref class List {};

generic <typename T>

ref class Queue : public List<T> {};

c570k3f3.collapse_all(zh-tw,VS.110).gif條件約束

限制式是一項限制,就可以做為型別參數的型別。 例如,給定的泛用類別無法接受來自指定的類別,繼承的類別或實作指定的介面。 如需詳細資訊,請參閱 泛型型別參數的條件約束 (C++/CLI)

參考型別和實值型別

控制代碼型別和實值型別可能會當做型別引數。 在泛型定義中,在其中可使用兩種類型,語法是參考型別。 例如, **->**運算子用來存取的型別參數的型別成員,不論最後使用的型別是否為參考型別或實值型別。 型別引數為使用實值型別時,執行階段會產生程式碼使用實值型別,而直接的boxing不實值型別。

當使用參考型別做為泛型型別引數,使用的控制代碼的語法。 當使用實值型別做為泛型型別引數,請直接使用的型別名稱。

// generics_overview_2.cpp

// compile with: /clr

generic <typename T>

ref class GenericType {};

ref class ReferenceType {};

value struct ValueType {};

int main() {

GenericType<ReferenceType^> x;

GenericType<ValueType> y;

}

型別參數

在泛型類別的型別參數被視為其他識別項。 不過,因為無法得知型別,並沒有限制它們的用法。 比方說,您無法使用成員與類別的型別參數的方法,除非已知來支援這些成員的型別參數。 也就是透過來存取成員型別參數,您必須加入包含至該型別參數的限制式清單成員的型別。

// generics_overview_3.cpp

// compile with: /clr

interface class I {
   void f1();
   void f2();
};

ref struct R : public I {
   virtual void f1() {}
   virtual void f2() {} 
   virtual void f3() {} 
};

generic <typename T>
where T : I
void f(T t) {
   t->f1();
   t->f2();
   safe_cast<R^>(t)->f3();
}

int main() {
   f(gcnew R());
}

這些限制套用至運算子也。 不受限制的泛型型別參數不可以使用==和!=運算子來比較兩個執行個體型別參數,在 [大小寫的型別不支援這些運算子。 這些檢查項目所需的泛型,但不是為範本,因為泛型可能專門用來與任何類別的執行階段,符合條件約束,當但會來不及檢查是否有不正確的成員使用。

型別參數的預設執行個體可能會建立使用()運算子。 例如:

T t = T();

其中T是在泛型類別或方法定義的型別參數、 它的預設值將變數初始化。 如果T是一種 ref類別就會發現 null指標。 如果T是實值類別,物件會初始化為零。 這就稱為預設初始設定式。

請參閱

其他資源

泛型 (C++ 元件擴充功能)