ジェネリック型パラメーターの制約 (C++/CLI)Constraints on Generic Type Parameters (C++/CLI)

ジェネリック型またはメソッドの宣言では、型パラメーターを制約で修飾できます。In generic type or method declarations, you can qualify a type parameter with constraints. 制約は、型引数として使用される型が満たす必要がある要件です。A constraint is a requirement that types used as type arguments must satisfy. たとえば、型引数で特定のインターフェイスを実装するか特定のクラスから継承する必要があるという制約が可能です。For example, a constraint might be that the type argument must implement a certain interface or inherit from a specific class.

制約は省略可能です。パラメーターに制約の指定がないことは、そのパラメーターを Object に制限するのと同じです。Constraints are optional; not specifying a constraint on a parameter is equivalent to constraining that parameter to Object.

構文Syntax

where type-parameter: constraint list

パラメーターParameters

type-parametertype-parameter
制約が適用される、いずれかの型パラメーター。One of the type parameters, to be constrained.

constraint listconstraint list
constraint list は、制約の指定のコンマ区切りの一覧です。constraint list is a comma-separated list of constraint specifications. 一覧には、型パラメーターによって実装されるインターフェイスを含めることができます。The list can include interfaces to be implemented by the type parameter.

一覧には、クラスを含めることもできます。The list can also include a class. 型引数で基底クラスの制約を満たすには、制約と同じクラスにするか、制約から派生する必要があります。For the type argument to satisfy a base class constraint, it must be the same class as the constraint or derive from the constraint.

gcnew() を指定して型引数にパラメーターのないコンストラクターが含まれている必要があること、または ref class を指定して型引数に参照型 (任意のクラス、インターフェイス、デリゲート、または配列型) が含まれている必要があること、または value class を指定して型引数に値型が含まれていることを指定することもできます。You can also specify gcnew() to indicate the type argument must have a public parameterless constructor; or ref class to indicate the type argument must be a reference type, including any class, interface, delegate, or array type; or value class to indicate the type argument must be a value type. Nullable<T> を除く任意の値型を指定できます。Any value type except Nullable<T> can be specified.

制約としてジェネリック パラメーターを指定することもできます。You can also specify a generic parameter as a constraint. 制約が適用されている型に提供される型引数は、制約の型から派生する必要があります。The type argument supplied for the type you are constraining must be or derive from the type of the constraint. これは、生の型制約と呼ばれます。This is called a naked type constraint.

解説Remarks

制約句は where、型パラメーター、コロン ( : )、および制約で構成され、型パラメーターに対する制約の性質を規定します。The constraint clause consists of where followed by a type parameter, a colon (:), and the constraint, which specifies the nature of the restriction on the type parameter. where は状況依存キーワードです。詳細については、「状況依存キーワード」を参照してください。where is a context-sensitive keyword; see Context-Sensitive Keywords for more information. 複数の where 句はスペースで分離します。Separate multiple where clauses with a space.

制約を型パラメーターに適用して、ジェネリック型またはメソッドの引数として使用できる型に制限を課します。Constraints are applied to type parameters to place limitations on the types that can be used as arguments for a generic type or method.

クラスまたはインターフェイスの制約では、引数の型が特定のクラスである、特定のクラスから継承される、または特定のインターフェイスを実装する必要があることを指定します。Class and interface constraints specify that the argument types must be or inherit from a specified class or implement a specified interface.

ジェネリック型またはメソッドに対する制約の適用によって、その型またはメソッドのコードで、制約付きの型の既知の機能を活用できます。The application of constraints to a generic type or method allows code in that type or method to take advantage of the known features of the constrained types. たとえば、型パラメーターで IComparable<T> インターフェイスが実装されるようにジェネリック クラスを宣言できます。For example, you can declare a generic class such that the type parameter implements the IComparable<T> interface:

// generics_constraints_1.cpp
// compile with: /c /clr
using namespace System;
generic <typename T>
where T : IComparable<T>
ref class List {};

この制約では、T で使用される型引数は、コンパイル時に IComparable<T> を実装することを要求します。This constraint requires that a type argument used for T implements IComparable<T> at compile time. CompareTo などのインター フェイスメソッドを呼び出すこともできます。It also allows interface methods, such as CompareTo, to be called. インターフェイス メソッドを呼び出す型パラメーターのインスタンスへのキャストは必要ありません。No cast is needed on an instance of the type parameter to call interface methods.

型パラメーターを介して型引数のクラスの静的メソッドを呼び出すことはできません。それらは、実際の名前付きの型を介してのみ呼び出すことができます。Static methods in the type argument's class cannot be called through the type parameter; they can be called only through the actual named type.

intdouble などの組み込み型を含め、制約を値型にすることはできません。A constraint cannot be a value type, including built-in types such as int or double. 値型は派生クラスを持つことができないため、1 つのクラスのみが制約を満たすことができます。Since value types cannot have derived classes, only one class would ever be able to satisfy the constraint. その場合は、特定の値の型に置き換えられた型パラメーターを使用して、ジェネリックを書き換えることができます。In that case, the generic can be rewritten with the type parameter replaced by the specific value type.

不明な型でメソッドやインターフェイスがサポートされていることが制約で示唆されない限り、コンパイラで不明な型のメソッドやその他の機能は使用できないため、制約が必要な場合があります。Constraints are required in some cases since the compiler will not allow the use of methods or other features of an unknown type unless the constraints imply that the unknown type supports the methods or interfaces.

同じ型パラメーターに対して、コンマ区切りの一覧で複数の制約を指定できます。Multiple constraints for the same type parameter can be specified in a comma-separated list

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

複数の型パラメーターがある場合は、型パラメーターごとに 1 つの where 句を使用します。With multiple type parameters, use one where clause for each type parameter. 次に例を示します。For example:

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

まとめると、コードでは、次の規則に従って制約を使用します。To summarize, use constraints in your code according to the following rules:

  • 複数の制約を一覧で指定する場合は、任意の順序で指定できます。If multiple constraints are listed, the constraints may be listed in any order.

  • 制約は、抽象基底クラスなどのクラス型も可能です。Constraints can also be class types, such as abstract base classes. ただし、制約は、値型またはシール クラスをすることはできません。However, constraints cannot be value types or sealed classes.

  • 制約自体が型パラメーターになることはできませんが、オープン構築型の型パラメーターを含めることができます。Constraints cannot themselves be type parameters, but they can involve the type parameters in an open constructed type. 次に例を示します。For example:

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

Example

次の例では、制約を使用して、型パラメーターでインスタンス メソッドを呼び出すことを示します。The following example demonstrates using constraints to call instance methods on type parameters.

// 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");
}
"parent" is not a senior
"grandfather" is a senior

Example

制約としてジェネリック型パラメーターを使用すると、生の型制約が呼び出されます。When a generic type parameter is used as a constraint, it is called a naked type constraint. 生の型制約は、独自の型パラメーターを持つ名前付き関数で、パラメーターの型パラメーターをコンテナー型に制限する必要がある場合に有用です。Naked type constraints are useful when a member function with its own type parameter needs to constrain that parameter to the type parameter of the containing type.

次の例では、TAdd メソッドのコンテキストでの生の型制約になります。In the following example, T is a naked type constraint in the context of the Add method.

生の型制約は、ジェネリック クラス定義でも使用できます。Naked type constraints can also be used in generic class definitions. ジェネリック クラスでの生の型制約としての有用性は限られています。これは、コンパイラでは、Object から派生することを除き、生の型制約に関して想定できることがないためです。The usefulness of naked type constraints with generic classes is limited because the compiler can assume nothing about a naked type constraint except that it derives from Object. 2 つの型パラメーター間に継承関係を適用するシナリオには、ジェネリック クラスに対する生の型制約を使用してください。Use naked type constraints on generic classes in scenarios in which you wish to enforce an inheritance relationship between two type parameters.

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

関連項目See also

ジェネリックGenerics