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 have.

たとえば、型パラメーター 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. 基底クラスの制約を使用する場合は、型パラメーターに関する制約よりも前に制約を記述する必要があります。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 も基底クラスの制約として許可されていません。Before 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 { }

C# 8.0 以降の null 許容コンテキストでは、基本クラス型の null 許容属性が適用されます。In a nullable context in C# 8.0 and later, the nullability of the base class type is enforced. 基底クラスが null 非許容の場合 (たとえば、Base)、型引数は null 非許容である必要があります。If the base class is non-nullable (for example Base), the type argument must be non-nullable. 基底クラスが null 許容の場合 (Base? など)、型引数は null 許容型または null 非許容型のいずれかになります。If the base class is nullable (for example Base?), the type argument may be either a nullable or non-nullable reference type. 基底クラスが null 非許容であるときに、型引数が null 許容の参照型である場合、コンパイラからは警告を発行されます。The compiler issues a warning if the type argument is a nullable reference type when the base class is non-nullable.

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

C# 8.0 以降の null 許容コンテキストでは、class 制約には、型が null 非許容の参照型である必要があります。In a nullable context in C# 8.0 and later, the class constraint requires a type to be a non-nullable reference type. null 許容の参照型を許可するには、class? 制約を使用して、null 許容と null 非許容の参照型の両方を許可します。To allow nullable reference types, use the class? constraint, which allows both nullable and non-nullable reference types.

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 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