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.

例如,您可以宣告泛型類別 MyGenericClass,讓型別參數 T 實作 IComparable<T> 介面: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. 某些型別不允許作為基底類別條件約束:ObjectArrayValueTypeSome 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 子句可以指定型別是 classstructThe 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. 下列範例顯示 classstruct 條件約束: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. 從C# 8.0 開始,針對nullable enable 內容中編譯的程式碼,可以使用 notnull 條件約束。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# 撰寫低階 Interop 程式碼。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 條件約束會強制型別必須是 structThe 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 子句,例如: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