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

Egy általános definícióban a where záradék használatával megszűkíteni tudja azokat a típusokat, amelyeket argumentumként használ egy általános típus, metódus, delegálás vagy helyi függvény típusparamétereihez. Megadhat interfészeket, alaposztályokat, vagy megkövetelheti, hogy egy általános típus hivatkozás, érték vagy nem felügyelt típus legyen. Ezek a korlátozások deklarálják azokat a képességeket, amelyekkel a típusargumentumnak rendelkeznie kell. Helyezze a záradékot bármely where deklarált alaposztály vagy implementált illesztő után.

A C# nyelv referenciadokumentuma a C# nyelv legújabb kiadású verzióját ismerteti. Emellett a közelgő nyelvi kiadás nyilvános előzetes verziójú funkcióinak kezdeti dokumentációját is tartalmazza.

A dokumentáció azonosítja azokat a funkciókat, amelyeket először a nyelv utolsó három verziójában vagy az aktuális nyilvános előzetes verziókban vezetnek be.

Jótanács

Ha meg szeretné tudni, hogy mikor jelent meg először egy funkció a C#-ban, tekintse meg a C# nyelvi verzióelőzményeiről szóló cikket.

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éter egyéb megkötései 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 fordító 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. 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);

}

default A kényszer használatával 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

Olyan általános deklarációkat is használhat, amelyek a notnull kényszert null értékű, oblivious környezetben tartalmazzák, de a fordító 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 { }

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