where (generic type constraint) (C#-verwijzing)
De where
component in een algemene definitie geeft beperkingen op voor de typen die worden gebruikt als argumenten voor typeparameters in een algemeen type, methode, gemachtigde of lokale functie. Beperkingen kunnen interfaces, basisklassen opgeven of vereisen dat een algemeen type een verwijzing, waarde of onbeheerd type is. Ze declareren mogelijkheden die het typeargument moet hebben en moeten worden geplaatst na een gedeclareerde basisklasse of geïmplementeerde interfaces.
U kunt bijvoorbeeld een algemene klasse declareren, AGenericClass
zodat de typeparameter T
de IComparable<T> interface implementeert:
public class AGenericClass<T> where T : IComparable<T> { }
Notitie
Zie waar de component is voor meer informatie over de where-component in een query-expressie.
De where
component kan ook een basisklassebeperking bevatten. De beperking basisklasse geeft aan dat een type dat moet worden gebruikt als een typeargument voor dat algemene type de opgegeven klasse als basisklasse heeft, of dat is die basisklasse. Als de beperking van de basisklasse wordt gebruikt, moet deze worden weergegeven vóór andere beperkingen voor die typeparameter. Sommige typen zijn niet toegestaan als basisklassebeperking: Object, Arrayen ValueType. In het volgende voorbeeld ziet u de typen die nu kunnen worden opgegeven als basisklasse:
public class UsingEnum<T> where T : System.Enum { }
public class UsingDelegate<T> where T : System.Delegate { }
public class Multicaster<T> where T : System.MulticastDelegate { }
In een null-context wordt de null-waarde van het type basisklasse afgedwongen. Als de basisklasse niet null kan worden gebruikt (bijvoorbeeld Base
), moet het typeargument niet null zijn. Als de basisklasse nullable is (bijvoorbeeld Base?
), kan het typeargument een null-verwijzingstype of een niet-null-verwijzingstype zijn. De compiler geeft een waarschuwing uit als het typeargument een null-verwijzingstype is wanneer de basisklasse niet nullbaar is.
De where
component kan opgeven dat het type een class
of een struct
is. De struct
beperking verwijdert de noodzaak om een basisklassebeperking van System.ValueType
. Het System.ValueType
type kan niet worden gebruikt als basisklassebeperking. In het volgende voorbeeld ziet u zowel de beperkingen als class
de struct
beperkingen:
class MyClass<T, U>
where T : class
where U : struct
{ }
In een null-context vereist de class
beperking dat een type een niet-null-verwijzingstype is. Als u null-verwijzingstypen wilt toestaan, gebruikt u de class?
beperking, waarmee zowel nullable als niet-nullable verwijzingstypen zijn toegestaan.
De where
component kan de notnull
beperking bevatten. De notnull
beperking beperkt de typeparameter tot niet-nullable typen. Het type kan een waardetype of een niet-null-verwijzingstype zijn. De notnull
beperking is beschikbaar voor code die in een nullable enable
context is gecompileerd. In tegenstelling tot andere beperkingen, als een typeargument de notnull
beperking schendt, genereert de compiler een waarschuwing in plaats van een fout. Waarschuwingen worden alleen gegenereerd in een nullable enable
context.
De toevoeging van null-referentietypen introduceert een mogelijke dubbelzinnigheid in de betekenis van T?
algemene methoden. Als T
het een struct
, T?
is hetzelfde als System.Nullable<T>. Als T
dit echter een verwijzingstype is, T?
betekent dit een null
geldige waarde. De dubbelzinnigheid ontstaat omdat het overschrijven van methoden geen beperkingen kan bevatten. Met de nieuwe default
beperking wordt deze dubbelzinnigheid opgelost. U voegt deze toe wanneer een basisklasse of -interface twee overbelastingen van een methode declareert, een die de struct
beperking aangeeft en een die niet de of struct
de class
beperking heeft toegepast:
public abstract class B
{
public void M<T>(T? item) where T : struct { }
public abstract void M<T>(T? item);
}
U gebruikt de default
beperking om op te geven dat de afgeleide klasse de methode overschrijft zonder de beperking in uw afgeleide klasse of expliciete interface-implementatie. Dit is alleen geldig voor methoden die basismethoden overschrijven of expliciete interface-implementaties:
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 { }
}
Belangrijk
Algemene declaraties die de notnull
beperking bevatten, kunnen worden gebruikt in een lege context, maar compiler dwingt de beperking niet af.
#nullable enable
class NotNullContainer<T>
where T : notnull
{
}
#nullable restore
De where
component kan ook een unmanaged
beperking bevatten. De unmanaged
beperking beperkt de typeparameter tot typen die niet-beheerde typen worden genoemd. Met unmanaged
deze beperking kunt u eenvoudiger interopcode op laag niveau schrijven in C#. Deze beperking maakt herbruikbare routines mogelijk voor alle niet-beheerde typen. De unmanaged
beperking kan niet worden gecombineerd met de class
of struct
beperking. De unmanaged
beperking dwingt af dat het type een struct
:
class UnManagedWrapper<T>
where T : unmanaged
{ }
De where
component kan ook een constructorbeperking bevatten, new()
. Met deze beperking kunt u een exemplaar van een typeparameter maken met behulp van de new
operator. De nieuwe() beperking laat de compiler weten dat elk opgegeven typeargument een toegankelijke parameterloze constructor moet hebben. Voorbeeld:
public class MyGenericClass<T> where T : IComparable<T>, new()
{
// The following line is not possible without new() constraint:
T item = new T();
}
De new()
beperking wordt als laatste weergegeven in de where
component, tenzij deze wordt gevolgd door de allows ref struct
antibeperking. De new()
beperking kan niet worden gecombineerd met de struct
of unmanaged
beperkingen. Alle typen die aan deze beperkingen voldoen, moeten een toegankelijke parameterloze constructor hebben, waardoor de new()
beperking overbodig wordt.
Met deze antibeperking wordt aangegeven dat het typeargument T
een ref struct
type kan zijn. Voorbeeld:
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)
{
}
}
Het algemene type of de methode moet voldoen aan de veiligheidsregels voor ref voor elk exemplaar, T
omdat het een ref struct
. De allows ref struct
component kan niet worden gecombineerd met de class
of class?
beperking. De allows ref struct
antibeperking moet alle beperkingen voor dat typeargument volgen.
Gebruik bij meerdere typeparameters één where
component voor elke typeparameter, bijvoorbeeld:
public interface IMyInterface { }
namespace CodeExample
{
class Dictionary<TKey, TVal>
where TKey : IComparable<TKey>
where TVal : IMyInterface
{
public void Add(TKey key, TVal val) { }
}
}
U kunt ook beperkingen koppelen aan typeparameters van algemene methoden, zoals wordt weergegeven in het volgende voorbeeld:
public void MyMethod<T>(T t) where T : IMyInterface { }
U ziet dat de syntaxis voor het beschrijven van parameterbeperkingen voor gemachtigden hetzelfde is als die van methoden:
delegate T MyDelegate<T>() where T : new();
Zie Algemene gemachtigden voor informatie over algemene gemachtigden.
Zie Beperkingen voor typeparameters voor meer informatie over de syntaxis en het gebruik van beperkingen.
C#-taalspecificatie
Zie de C#-taalspecificatie voor meer informatie. De taalspecificatie is de definitieve bron voor de C#-syntaxis en het gebruik.