where (omezení obecného typu) (Referenční dokumentace jazyka C#)
Klauzule where
v obecné definici určuje omezení typů, které se používají jako argumenty pro parametry typu v obecném typu, metodě, delegátu nebo místní funkci. Omezení mohou určovat rozhraní, základní třídy nebo vyžadovat obecný typ, aby byl odkaz, hodnota nebo nespravovaný typ. Deklarují schopnosti, které musí mít argument typu, a musí být umístěny po jakékoli deklarované základní třídě nebo implementovaných rozhraních.
Můžete například deklarovat obecnou třídu, AGenericClass
aby parametr T
typu implementuje IComparable<T> rozhraní:
public class AGenericClass<T> where T : IComparable<T> { }
Klauzule where
může také zahrnovat omezení základní třídy. Omezení základní třídy uvádí, že typ, který se má použít jako argument typu pro tento obecný typ, má zadanou třídu jako základní třídu, nebo je tato základní třída. Pokud se použije omezení základní třídy, musí se zobrazit před všemi dalšími omezeními daného parametru typu. Některé typy jsou zakázány jako omezení základní třídy: Object, Arraya ValueType. Následující příklad ukazuje typy, které lze nyní zadat jako základní třídu:
public class UsingEnum<T> where T : System.Enum { }
public class UsingDelegate<T> where T : System.Delegate { }
public class Multicaster<T> where T : System.MulticastDelegate { }
V kontextu s možnou hodnotou null je vynucena nullability základního typu třídy. Pokud je základní třída nenulová (například Base
), musí být argument typu nenulový. Pokud je základní třída nullable (například Base?
), může být argument typu nullable nebo nenulový odkazový typ. Kompilátor vydá upozornění v případě, že argument typu je odkazovatelný typ null, pokud základní třída není nullable.
Klauzule where
může určit, že typ je nebo class
struct
. Omezení struct
odebere nutnost zadat omezení System.ValueType
základní třídy . Typ System.ValueType
nelze použít jako omezení základní třídy. Následující příklad ukazuje omezení class
i struct
omezení:
class MyClass<T, U>
where T : class
where U : struct
{ }
V kontextu s možnou class
hodnotou null vyžaduje omezení, aby typ byl nenulový odkazový typ. Chcete-li povolit odkazové typy s možnou class?
hodnotou null, použijte omezení, které umožňuje odkazové typy s možnou hodnotou null i bez hodnoty null.
Klauzule where
může obsahovat notnull
omezení. Omezení notnull
omezuje parametr typu na typy bez hodnoty null. Typ může být typ hodnoty nebo nenulový odkazový typ. Omezení notnull
je k dispozici pro kód zkompilovaný v nullable enable
kontextu. Na rozdíl od jiných omezení, pokud argument typu porušuje notnull
omezení, kompilátor místo chyby vygeneruje upozornění. Upozornění se generují jenom v nullable enable
kontextu.
Přidání referenčních typů s možnou hodnotou null představuje potenciální nejednoznačnost ve významu T?
obecných metod. Pokud T
je , struct
T?
je stejný jako System.Nullable<T>. Pokud T
je však typ odkazu, znamená to, T?
že null
je platná hodnota. Nejednoznačnost vzniká, protože přepsání metod nemůže zahrnovat omezení. Nové default
omezení tuto nejednoznačnost vyřeší. Přidáte ho, když základní třída nebo rozhraní deklaruje dvě přetížení metody, jedna, která určuje struct
omezení a jedna, která nemá buď struct
použité omezení, nebo class
omezení:
public abstract class B
{
public void M<T>(T? item) where T : struct { }
public abstract void M<T>(T? item);
}
Pomocí default
omezení určíte, že odvozená třída přepíše metodu bez omezení v odvozené třídě nebo explicitní implementace rozhraní. Platí pouze pro metody, které přepisují základní metody nebo explicitní implementace rozhraní:
public class D : B
{
// Without the "default" constraint, the compiler tries to override the first method in B
public override void M<T>(T? item) where T : default { }
}
Důležité
Obecné deklarace, které obsahují omezení, lze použít v nezapomnělém kontextu s možnou notnull
hodnotou null, ale kompilátor nevynucuje omezení.
#nullable enable
class NotNullContainer<T>
where T : notnull
{
}
#nullable restore
Klauzule where
může obsahovat unmanaged
také omezení. Omezení unmanaged
omezuje parametr typu na typy označované jako nespravované typy. Omezení unmanaged
usnadňuje psaní kódu zprostředkovatele komunikace nízké úrovně v jazyce C#. Toto omezení umožňuje opakovaně použitelné rutiny napříč všemi nespravovanými typy. Omezení unmanaged
nelze kombinovat s class
omezením.struct
Omezení unmanaged
vynucuje, že typ musí být :struct
class UnManagedWrapper<T>
where T : unmanaged
{ }
Klauzule where
může také obsahovat omezení konstruktoru, new()
. Toto omezení umožňuje vytvořit instanci parametru typu pomocí operátoru new
. Omezení new() kompilátoru informuje, že jakýkoli zadaný argument typu musí mít přístupný konstruktor bez parametrů. Příklad:
public class MyGenericClass<T> where T : IComparable<T>, new()
{
// The following line is not possible without new() constraint:
T item = new T();
}
Omezení new()
se zobrazí jako poslední v where
klauzuli, pokud nebude následovat allows ref struct
anti-constraint. Omezení new()
nelze kombinovat s omezenímistruct
.unmanaged
Všechny typy, které splňují tato omezení, musí mít přístupný konstruktor bez parametrů, aby new()
bylo omezení redundantní.
Toto anti-constraint deklaruje, že argument typu může T
být ref struct
typ. Příklad:
public class GenericRefStruct<T> where T : allows ref struct
{
// Scoped is allowed because T might be a ref struct
public void M(scoped T parm)
{
}
}
Obecný typ nebo metoda musí dodržovat pravidla bezpečnosti ref pro libovolnou T
instanci, protože ref struct
může být . Klauzuli allows ref struct
nelze kombinovat s class
omezením.class?
Anti-constraint allows ref struct
musí dodržovat všechna omezení pro tento argument typu.
U více parametrů typu použijte jednu where
klauzuli pro každý parametr typu, například:
public interface IMyInterface { }
namespace CodeExample
{
class Dictionary<TKey, TVal>
where TKey : IComparable<TKey>
where TVal : IMyInterface
{
public void Add(TKey key, TVal val) { }
}
}
Omezení můžete také připojit k parametrům typů obecných metod, jak je znázorněno v následujícím příkladu:
public void MyMethod<T>(T t) where T : IMyInterface { }
Všimněte si, že syntaxe popisování omezení parametrů typu u delegátů je stejná jako u metod:
delegate T MyDelegate<T>() where T : new();
Informace o obecných delegátech najdete v tématu Obecné delegáty.
Podrobnosti o syntaxi a použití omezení najdete v tématu Omezení parametrů typu.
specifikace jazyka C#
Další informace najdete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.