泛型类型参数的约束 (C++/CLI)

在泛型类型或方法声明,则可以限定该约束的类型参数。 约束是类型的要求,类型参数必须满足。 例如,约束可能是类型参数必须实现某接口或从特定类继承。

约束是可选的;未指定约束在参数与约束该参数等效于 Object

where type-parameter: constraint list

参数

  • 类型参数
    一个类型参数,将约束。

  • 约束列表
    约束列表 是逗号分隔的列表约束规范。 列表可以包括类型将实现的接口参数。

    此列表还可包括类。 对于类型都满足某基类约束的参数,它必须是同一个类与约束或从绑定派生。

    还可以指定 gcnew() 指示该类型参数必须具有公共的无参数构造函数;或指示该类型的 ref class 参数必须是引用类型,包括任何类、接口、委托或数组类型;或指示该类型的 value class 参数必须是值类型。 除可以为 null 的 <T> 的任何值类型进行指定。

    还可以指定泛型参数作为约束。 该类型为绑定类型提供的参数必须是或从绑定的类型派生。 这称为一个裸类型约束。

备注

约束子句包括类型参数,冒号 (:) 和约束执行的 where ,类型参数指定该限制的性质。 where 是上下文相关关键字;有关更多 上下文相关的关键字(C++ 组件扩展) 信息。 用空格分隔多个 where 子句。

约束适用于具有限制类型参数在可用作参数为泛型类型或方法的类型。

类和接口约束指定参数类型必须是或从指定的类继承或实现了指定接口。

约束的应用程序对泛型类型或方法的允许在该类型或方法中的代码使用绑定类型的已知函数。 例如,可以声明泛型类这样该类型参数实现 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 或 double。 因为值类型不能有派生类,因此,只有一个类可以满足约束。 在这种情况下,泛型可以将复盖该类型特定值类型替换参数。

在某些情况下需要约束,因为编译器不允许使用方法或未知类型的其他功能,除非约束表示未知类型支持方法或接口。

相同类型的参数多个约束以逗号分隔的可指定列表

// 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 {};

多个类型参数,为每个类型参数使用一 where 子句。 例如:

// 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");
}
  

在泛型类型参数用作绑定时,将调用一个裸类型约束。 ,在使用自己的类型参数的成员函数需要约束该参数给包含的类型时,的类型参数裸类型约束很有用。

在下面的示例中, T 为一个裸类型约束在 " 添加方法中。

裸类型约束还可用于泛型类定义。 裸类型约束的作用与泛型类的是有限的,因为编译器都不能假定某个裸类型约束,但它从 Object派生。 使用在泛型类的裸类型约束在要强制两个类型参数之间的继承关系的方案。

// 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 {};

请参见

其他资源

泛型(C++ 组件扩展)