Sterk getypte gemachtigden
In het vorige artikel hebt u gezien dat u specifieke gedelegeerdentypen maakt met behulp van het delegate
trefwoord.
De abstracte klasse Delegate biedt de infrastructuur voor losse koppeling en aanroep. Concrete gedelegeerdentypen worden veel nuttiger door typeveiligheid te omarmen en af te dwingen voor de methoden die worden toegevoegd aan de aanroeplijst voor een gedelegeerde-object. Wanneer u het delegate
trefwoord gebruikt en een concreet type gemachtigde definieert, genereert de compiler deze methoden.
In de praktijk zou dit leiden tot het maken van nieuwe typen gemachtigden wanneer u een andere methodehandtekening nodig hebt. Dit werk kan na een tijd vervelend worden. Voor elke nieuwe functie zijn nieuwe typen gemachtigden vereist.
Gelukkig is dit niet nodig. Het .NET Core-framework bevat verschillende typen die u opnieuw kunt gebruiken wanneer u gedelegeerdentypen nodig hebt. Dit zijn algemene definities, zodat u aanpassingen kunt declareren wanneer u nieuwe methodedeclaraties nodig hebt.
De eerste van deze typen is het Action type en verschillende variaties:
public delegate void Action();
public delegate void Action<in T>(T arg);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
// Other variations removed for brevity.
De in
wijzigingsfunctie voor het algemene typeargument wordt behandeld in het artikel over covariantie.
Er zijn variaties van de Action
gemachtigde die maximaal 16 argumenten bevatten, zoals Action<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>.
Het is belangrijk dat deze definities verschillende algemene argumenten gebruiken voor elk van de gedelegeerde argumenten: Dat biedt u maximale flexibiliteit. De methodeargumenten hoeven niet te zijn, maar kunnen hetzelfde type zijn.
Gebruik een van de Action
typen voor elk gemachtigde type met een ongeldig retourtype.
Het framework bevat ook verschillende algemene gedelegeerdentypen die u kunt gebruiken voor gedelegeerdentypen die waarden retourneren:
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T1, out TResult>(T1 arg);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
// Other variations removed for brevity
De out
wijzigingsfunctie voor het argument voor het algemene resultaattype wordt behandeld in het artikel over covariantie.
Er zijn variaties van de Func
gemachtigde met maximaal 16 invoerargumenten, zoals Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>.
Het type van het resultaat is altijd de laatste typeparameter in alle Func
declaraties, volgens conventie.
Gebruik een van de Func
typen voor elk gemachtigde type dat een waarde retourneert.
Er is ook een speciaal Predicate<T> type voor een gemachtigde die een test retourneert op één waarde:
public delegate bool Predicate<in T>(T obj);
U ziet mogelijk dat voor elk Predicate
type een structureel equivalent Func
type bestaat, bijvoorbeeld:
Func<string, bool> TestForString;
Predicate<string> AnotherTestForString;
U denkt misschien dat deze twee typen gelijkwaardig zijn. Dat zijn ze niet. Deze twee variabelen kunnen niet door elkaar worden gebruikt. Aan een variabele van het ene type kan het andere type niet worden toegewezen. Het C#-typesysteem gebruikt de namen van de gedefinieerde typen, niet de structuur.
Al deze definities van gedelegeerdentypen in de .NET Core-bibliotheek moeten betekenen dat u geen nieuw gedelegeerdentype hoeft te definiëren voor een nieuwe functie die u maakt waarvoor gemachtigden zijn vereist. Deze algemene definities moeten alle typen gemachtigden bevatten die u in de meeste situaties nodig hebt. U kunt eenvoudig een exemplaar van een van deze typen maken met de vereiste typeparameters. In het geval van algoritmen die algemeen kunnen worden gemaakt, kunnen deze gemachtigden worden gebruikt als algemene typen.
Dit bespaart tijd en minimaliseert het aantal nieuwe typen dat u moet maken om met gedelegeerden te kunnen werken.
In het volgende artikel ziet u verschillende algemene patronen voor het werken met gemachtigden in de praktijk.