Megosztás a következőn keresztül:


where (általános típuskorlátozás) (C# referencia)

Az where általános definíció záradéka a típusparaméterek argumentumaként használt típusokra vonatkozó korlátozásokat határozza meg egy általános típusban, metódusban, delegálásban vagy helyi függvényben. A korlátozások megadhatnak interfészeket, alaposztályokat, vagy megkövetelhetik, hogy egy általános típus hivatkozás, érték vagy nem felügyelt típus legyen. Deklarálják azokat a képességeket, amelyekkel a típusargumentumnak rendelkeznie kell, és minden deklarált alaposztály vagy implementált illesztő után kell elhelyezni.

Deklarálhat például egy általános osztályt, AGenericClasshogy a típusparaméter T implementálja az interfészt IComparable<T> :

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

Feljegyzés

A lekérdezési kifejezés hol található záradékával kapcsolatos további információkért tekintse meg a hol található záradékot.

A where záradék alaposztály-korlátozást is tartalmazhat. Az alaposztály-korlátozás azt állítja, hogy az adott általános típus típusargumentumaként használandó típus a megadott osztályt alaposztályként vagy alaposztályként használja. Ha az alaposztály-kényszert használja, annak az adott típusparaméterre vonatkozó egyéb megkötések előtt kell megjelennie. Egyes típusok nem engedélyezettek alaposztály-korlátozásként: Object, Arrayés ValueType. Az alábbi példa az alaposztályként megadható típusokat mutatja be:

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

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

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

Null értékű környezetben a rendszer kikényszeríti az alaposztálytípus nullságát. Ha az alaposztály nem null értékű (például Base), a típusargumentumnak nem null értékűnek kell lennie. Ha az alaposztály null értékű (például Base?), a típusargumentum lehet null értékű vagy nem null értékű hivatkozástípus. A fordító figyelmeztetést ad ki, ha a típusargumentum null értékű hivatkozástípus, ha az alaposztály nem null értékű.

A where záradék megadhatja, hogy a típus egy class vagy egy struct. A struct kényszer nem szükséges megadni egy alaposztály-korlátozást.System.ValueType A System.ValueType típus nem használható alaposztály-korlátozásként. Az alábbi példában a korlátozások és class a struct korlátozások is láthatók:

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

Null értékű környezetben a class kényszer megköveteli, hogy egy típus ne null értékű hivatkozástípus legyen. A null értékű hivatkozástípusok engedélyezéséhez használja a class? kényszert, amely lehetővé teszi a null értékű és a nem null értékű hivatkozástípusokat is.

A where záradék tartalmazhatja a kényszert notnull . A notnull kényszer a típusparamétert nem null értékű típusokra korlátozza. A típus lehet értéktípus vagy nem null értékű hivatkozástípus. A notnull kényszer elérhető a környezetbennullable enable. A többi kényszertől eltérően, ha egy típusargumentum megsérti a notnull kényszert, a fordító hibaüzenet helyett figyelmeztetést hoz létre. A figyelmeztetések csak egy nullable enable környezetben jönnek létre.

A null értékű referenciatípusok hozzáadása potenciális kétértelműséget vezet be az általános módszerek jelentésében T? . Ha T egy struct, akkor ugyanaz, T? mint System.Nullable<T>a . Ha T azonban hivatkozástípusról van szó, az azt jelenti, T? hogy null érvényes érték. A kétértelműség azért merül fel, mert a felülíró metódusok nem tartalmazhatnak korlátozásokat. Az új default korlátozás feloldja ezt a kétértelműséget. Akkor adja hozzá, ha egy alaposztály vagy felület egy metódus két túlterhelését deklarálja, egyet, amely megadja a struct kényszert, és egyet, amely nem alkalmazza a vagy a structclass kényszert:

public abstract class B
{
    public void M<T>(T? item) where T : struct { }
    public abstract void M<T>(T? item);

}

A kényszer használatával default megadhatja, hogy a származtatott osztály felülbírálja a metódust a származtatott osztály kényszere vagy explicit felületi implementáció nélkül. Csak az alap metódusokat felülbíráló metódusokra vagy explicit felületi implementációkra érvényes:

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

Fontos

A kényszert tartalmazó notnull általános deklarációk null értékű, oblivious környezetben használhatók, a fordító azonban nem kényszeríti ki a kényszert.

#nullable enable
    class NotNullContainer<T>
        where T : notnull
    {
    }
#nullable restore

A where záradék korlátozást unmanaged is tartalmazhat. A unmanaged korlátozás a típusparamétert nem felügyelt típusokra korlátozza. A unmanaged korlátozás megkönnyíti az alacsony szintű interop kód írását C#-ban. Ez a korlátozás minden nem felügyelt típus esetében lehetővé teszi az újrahasználható rutinokat. A unmanaged kényszer nem kombinálható a korlátozással vagy class a struct korlátozással. A unmanaged kényszer kikényszeríti, hogy a típusnak a következőnek kell lennie struct:

class UnManagedWrapper<T>
    where T : unmanaged
{ }

A where záradék konstruktor-kényszert is tartalmazhat. new() Ez a korlátozás lehetővé teszi egy típusparaméter példányának létrehozását az new operátor használatával. Az új() korlátozás tudatja a fordítóval, hogy a megadott típusargumentumoknak elérhető paraméter nélküli konstruktorsal kell rendelkezniük. Példa:

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

A new() kényszer utolsóként jelenik meg a where záradékban, hacsak nem követi az allows ref struct anti-kényszer. A new() kényszer nem kombinálható a korlátozásokkal vagy struct a unmanaged korlátozásokkal. A kényszernek megfelelő összes típusnak elérhető paraméter nélküli konstruktorsal kell rendelkeznie, így a new() kényszer redundánssá válik.

Ez az anti-korlátozás azt deklarálja, hogy a típus argumentuma T lehet típus ref struct . Példa:

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

    }
}

Az általános típusnak vagy metódusnak minden példányra be kell tartania T a ref biztonsági szabályokat, mert lehet, hogy egy ref struct. A allows ref struct záradék nem kombinálható a korlátozással vagy class a class? korlátozással. Az allows ref struct anti-kényszernek az adott típusargumentum összes kényszerét követnie kell.

Több típusparaméter esetén minden típusparaméterhez használjon egy where záradékot, például:

public interface IMyInterface { }

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

Az általános metódusok típusparamétereihez kényszereket is csatolhat, ahogyan az alábbi példában látható:

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

Figyelje meg, hogy a delegáltak típusparaméter-korlátozásait leíró szintaxis megegyezik a metódusok szintaxisával:

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

Az általános meghatalmazottakról további információt az Általános meghatalmazottak című témakörben talál.

A kényszerek szintaxisával és használatával kapcsolatos részletekért tekintse meg a típusparaméterekre vonatkozó korlátozásokat.

C# nyelvspecifikáció

További információkért lásd a C# nyelvi specifikációját. A nyelvi specifikáció a C#-szintaxis és -használat végleges forrása.

Lásd még