where (ジェネリック型制約) (C# リファレンス)where (generic type constraint) (C# Reference)

ジェネリック定義の where 句では、型の制約を指定します。この型は、ジェネリック型、メソッド、デリゲート、またはローカル関数における型パラメーターの引数として使用されます。The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. 制約では、インターフェイス (基底クラス) を指定したり、参照、値、またはアンマネージド型となるジェネリック型を要求したりすることができます。Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type. それらにより型引数が処理する必要がある機能が宣言されえます。They declare capabilities that the type argument must possess.

たとえば、型パラメーター TIComparable<T> インターフェイスを実装するように、次のように MyGenericClass ジェネリック クラスを宣言できます。For example, you can declare a generic class, MyGenericClass, such that the type parameter T implements the IComparable<T> interface:

public class AGenericClass<T> where T : IComparable<T> { }


クエリ式での where 句の詳細については、「where 句」を参照してください。For more information on the where clause in a query expression, see where clause.

where 句には基底クラスの制約を含めることもできます。The where clause can also include a base class constraint. 基底クラスの制約は、ジェネリック型の型引数として使用する型には、ジェネリック型の型引数として使用される基底クラスとして指定されているクラス (または基底クラス自体) が含まれている必要があることを指定します。The base class constraint states that a type to be used as a type argument for that generic type has the specified class as a base class (or is that base class) to be used as a type argument for that generic type. 基底クラスの制約を使用する場合は、型パラメーターに関する制約よりも前に制約を記述する必要があります。If the base class constraint is used, it must appear before any other constraints on that type parameter. 一部の型は、基底クラスの制約として許可されません (ObjectArrayValueType)。Some types are disallowed as a base class constraint: Object, Array, and ValueType. C# 7.3 より前は、EnumDelegateMulticastDelegate も基底クラスの制約として許可されていません。Prior to C# 7.3, Enum, Delegate, and MulticastDelegate were also disallowed as base class constraints. 次の例では、この型は基底クラスとして指定できるようになったことを示しています。The following example shows the types that can now be specified as a base class:

public class UsingEnum<T> where T : System.Enum { }

public class UsingDelegate<T> where T : System.Delegate { }

public class Multicaster<T> where T : System.MulticastDelegate { }

where 句では、型が class または struct であることを指定できます。The where clause can specify that the type is a class or a struct. struct 制約では、System.ValueType の基底クラスの制約を指定する必要はありません。The struct constraint removes the need to specify a base class constraint of System.ValueType. System.ValueType 型は基底クラスの制約として使用できません。The System.ValueType type may not be used as a base class constraint. class 制約と struct 制約の両方の例を次に示します。The following example shows both the class and struct constraints:

class MyClass<T, U>
    where T : class
    where U : struct
{ }

where 句には、notnull 制約を含めることができます。The where clause may include the notnull constraint. notnull 制約では、型パラメーターを null 非許容型に制限します。The notnull constraint limits the type parameter to non-nullable types. その型には、値型または null 非許容参照型を指定できます。That type may be a value type or a non-nullable reference type. notnull 制約は、C# 8.0 以降の nullable enable コンテキストでコンパイルされたコードで使用できます。The notnull constraint is available starting in C# 8.0 for code compiled in a nullable enable context. 他の制約とは異なり、型引数が notnull 制約に違反すると、コンパイラによりエラーではなく警告が生成されます。Unlike other constraints, if a type argument violates the notnull constraint, the compiler generates a warning instead of an error. 警告は、nullable enable コンテキストでのみ生成されます。Warnings are only generated in a nullable enable context.


notnull 制約が含まれるジェネリック宣言は、null 許容が未指定のコンテキストで使用できますが、コンパイラではその制約は強制されません。Generic declarations that include the notnull constraint can be used in a nullable oblivious context, but compiler does not enforce the constraint.

#nullable enable
    class NotNullContainer<T>
        where T : notnull

#nullable restore

where 句には、unmanaged 制約を含めることもできます。The where clause may also include an unmanaged constraint. unmanaged 制約では、アンマネージド型と呼ばれる型に対して型パラメーターを制限します。The unmanaged constraint limits the type parameter to types known as unmanaged types. unmanaged 制約を使用すると、C# でローレベルの相互運用コードを記述しやすくなります。The unmanaged constraint makes it easier to write low-level interop code in C#. この制約では、すべてのアンマネージド型にわたって再利用可能なルーチンを可能にします。This constraint enables reusable routines across all unmanaged types. unmanaged 制約は、classstruct 制約と組み合わせることはできません。The unmanaged constraint can't be combined with the class or struct constraint. unmanaged 制約は struct にする必要がある型を適用します。The unmanaged constraint enforces that the type must be a struct:

class UnManagedWrapper<T>
    where T : unmanaged
{ }

where 句には、コンストラクター制約 new() を含めることもできます。The where clause may also include a constructor constraint, new(). その制約では、new 演算子を使用して型パラメーターのインスタンスを作成できるようにします。That constraint makes it possible to create an instance of a type parameter using the new operator. new() 制約に基づいて、コンパイラは、指定されている型引数には、アクセス可能なパラメーターなしの (または既定の) コンストラクターが必要であることを認識します。The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless--or default-- constructor. 次に例を示します。For example:

public class MyGenericClass<T> where T : IComparable<T>, new()
    // The following line is not possible without new() constraint:
    T item = new T();

new() 制約は where 句の最後に示されます。The new() constraint appears last in the where clause. new() 制約は、structunmanaged 制約と組み合わせることはできません。The new() constraint can't be combined with the struct or unmanaged constraints. それらの制約を満たすすべての型には、new() 制約を重複させて、アクセス可能なパラメーターなしのコンストラクターが含まれている必要があります。All types satisfying those constraints must have an accessible parameterless constructor, making the new() constraint redundant.

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

public interface IMyInterface { }

namespace CodeExample
    class Dictionary<TKey, TVal>
        where TKey : IComparable<TKey>
        where TVal : IMyInterface
        public void Add(TKey key, TVal val) { }

次の例に示すように、ジェネリック メソッドの型パラメーターにも制約を適用できます。You can also attach constraints to type parameters of generic methods, as shown in the following example:

public void MyMethod<T>(T t) where T : IMyInterface { }

デリゲートに対する型パラメーター制約を記述する構文は、メソッドの構文と同じである点に注意してください。Notice that the syntax to describe type parameter constraints on delegates is the same as that of methods:

delegate T MyDelegate<T>() where T : new();

汎用デリゲートについては、「汎用デリゲート」を参照してください。For information on generic delegates, see Generic Delegates.

制約の構文と使用方法の詳細については、「型パラメーターの制約」を参照してください。For details on the syntax and use of constraints, see Constraints on Type Parameters.

C# 言語仕様C# language specification

詳細については、「C# 言語の仕様」を参照してください。For more information, see the C# Language Specification. 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。The language specification is the definitive source for C# syntax and usage.

関連項目See also