泛型型別參數的條件約束 (C++/CLI)
在泛型型別或方法宣告中,您可以限定型別參數條件約束。 限制式是當做型別引數的型別都必須滿足的需求。 例如,限制式可能是型別引數必須實作特定介面或繼承自特定類別。
條件約束是選擇性的。 未指定參數上的 [限制式相當於該參數的條件約束Object。
where type-parameter: constraint list
參數
型別參數
其中一個型別參數,要限制。限制式清單
限制式清單是逗點分隔的清單限制式規格。 此清單可以包含型別參數所實作的介面。清單也可以包含一個類別。 來滿足基底類別限制式的型別引數,它必須為限制式相同的類別或衍生自限制式。
您也可以指定gcnew() ,表示型別引數必須具有公用無參數建構函式。 或ref class ,表示型別引數必須是參考型別,包括類別、介面、委派,或陣列型別 ; 或value class ,表示型別引數必須是實值型別。 任何除了 Nullable <T> 的實值型別 您可以指定。
您也可以指定泛用參數當做限制式。 必須是型別引數的條件約束的型別,或是衍生自限制式的型別。 這就稱為 naked 型別限制式。
備註
限制式子句組成 , 後面接著型別參數,冒號 (:),和限制式,其型別參數上指定限制的本質。 其中是內容-寫的關鍵字。 請參閱視內容而有所區別的關鍵字 (C++ 元件擴充功能)如需詳細資訊。 區隔多個 , 子句加上空格。
條件約束會套用至型別參數無法置於可用來做為泛型型別或方法的引數的型別中的限制。
類別和介面條件約束指定引數型別必須是或從指定的類別繼承或實作指定的介面。
應用程式的泛型型別或方法的條件約束可讓該型別或方法,以利用已知的功能條件約束的型別中的程式碼。 例如,您可以宣告泛型類別的型別參數實作 **IComparable <T>**介面:
// generics_constraints_1.cpp
// compile with: /c /clr
using namespace System;
generic <typename T>
where T : IComparable<T>
ref class List {};
此限制式會需要型別引數用於 T實作IComparable<T>在編譯時期。 它也可讓介面方法,例如 CompareTo,而被呼叫。 沒有轉換型別參數的執行個體上才能呼叫介面方法。
型別引數類別的靜態方法不能被呼叫,透過型別參數。 它們只能透過實際的具名型別呼叫。
限制式不能是實值型別,包括內建的型別,例如int或雙。 因為實值型別不能有衍生類別,曾將能夠滿足限制式只能有一個類別。 在此大小寫中,就可以重寫泛用型別參數取代特定的實值型別。
由於編譯器將不允許的方法或其他的功能,未知的型別條件約束,指的未知的型別支援的方法或介面,除非在某些情況下需要的條件約束。
逗點分隔的清單中可以指定多個相同的型別參數的條件約束
// generics_constraints_2.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;
generic <typename T>
where T : List<T>, IComparable<T>
ref class List {};
使用多個型別參數時,使用其中一個 , 每個型別參數的子句。 例如:
// generics_constraints_3.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;
generic <typename K, typename V>
where K: IComparable<K>
where V: IComparable<K>
ref class Dictionary {};
若要總而言之,請根據下列規則來的程式程式碼中使用條件約束:
如果列出多個條件約束,條件約束可能會列出任何順序。
條件約束也可以是類別型別,例如抽象的基底類別。 然而,在實值型別或密封的類別不能進行條件約束。
條件約束無法本身為型別參數,但是它們可以涉及開啟建構的型別中的型別參數。 例如:
// generics_constraints_4.cpp // compile with: /c /clr generic <typename T> ref class G1 {}; generic <typename Type1, typename Type2> where Type1 : G1<Type2> // OK, G1 takes one type parameter ref class G2{};
範例
下列範例會示範使用型別參數上呼叫執行個體方法的條件約束。
// generics_constraints_5.cpp
// compile with: /clr
using namespace System;
interface class IAge {
int Age();
};
ref class MyClass {
public:
generic <class ItemType> where ItemType : IAge
bool isSenior(ItemType item) {
// Because of the constraint,
// the Age method can be called on ItemType.
if (item->Age() >= 65)
return true;
else
return false;
}
};
ref class Senior : IAge {
public:
virtual int Age() {
return 70;
}
};
ref class Adult: IAge {
public:
virtual int Age() {
return 30;
}
};
int main() {
MyClass^ ageGuess = gcnew MyClass();
Adult^ parent = gcnew Adult();
Senior^ grandfather = gcnew Senior();
if (ageGuess->isSenior<Adult^>(parent))
Console::WriteLine("\"parent\" is a senior");
else
Console::WriteLine("\"parent\" is not a senior");
if (ageGuess->isSenior<Senior^>(grandfather))
Console::WriteLine("\"grandfather\" is a senior");
else
Console::WriteLine("\"grandfather\" is not a senior");
}
如果泛型型別參數作為限制式,都稱為 naked 型別限制式。 當成員函式本身的型別參數需要限制為包含型別的型別參數的參數時,naked 型別條件約束會非常有用。
在下列範例中,t 是一 naked 型別限制式的 Add方法的內容中。
Naked 型別條件約束也可用在泛型類別定義中。 Naked 型別條件約束的泛型類別的使用性是有限的因為編譯器可以假設不瞭解 naked 型別限制式不同之處在於它是衍生自Object。 在您要強制兩型別參數之間的繼承關聯的情況下,使用泛型類別上的 naked 型別條件約束。
// generics_constraints_6.cpp
// compile with: /clr /c
generic <class T>
ref struct List {
generic <class U>
where U : T
void Add(List<U> items) {}
};
generic <class A, class B, class C>
where A : C
ref struct SampleClass {};