Dela via


Särskilja delegater och händelser

föregående

Utvecklare som är nya på .NET-plattformen kämpar ofta när de bestämmer sig för en design som baseras på delegates och en design som baseras på events. Valet av ombud eller händelser är ofta svårt, eftersom de två språkfunktionerna är liknande. Händelser skapas även med hjälp av språkstöd för ombud. En händelsehanterardeklaration deklarerar en ombudstyp.

Båda erbjuder ett scenario med sen bindning: de möjliggör scenarier där en komponent kommunicerar genom att anropa en metod som bara är känd vid körning. Båda stöder metoder för enstaka och flera prenumeranter. Du kan hitta dessa termer som single cast- (enskild sändning) och multicast-stöd (flersändning). Båda stöder liknande syntax för att lägga till och ta bort hanterare. När du skapar en händelse och anropar ett ombud används slutligen exakt samma metodanropssyntax. Båda stöder även samma Invoke() metodsyntax för användning med operatorn ?..

Med alla dessa likheter är det lätt att ha problem med att avgöra när du ska använda vilken.

Det är valfritt att lyssna på händelser

Det viktigaste när du ska avgöra vilken språkfunktion som ska användas är om det måste finnas en ansluten prenumerant eller inte. Om din kod måste anropa koden som tillhandahålls av prenumeranten bör du använda en design som baseras på delegeringar när du behöver implementera callback. Om koden kan slutföra allt sitt arbete utan att anropa prenumeranter bör du använda en design som baseras på händelser.

Tänk på exemplen som skapades under det här avsnittet. Koden som du skapade med List.Sort() måste ges en jämförelsefunktion för att elementen ska kunna sorteras korrekt. LINQ-frågor måste levereras med ombud för att avgöra vilka element som ska returneras. Båda använde en design som skapats med delegeringar.

Överväg händelsen Progress. Den rapporterar förlopp för en aktivitet. Uppgiften fortsätter att fortsätta om det finns några lyssnare eller inte. FileSearcher är ett annat exempel. Den skulle ändå söka och hitta alla filer som eftersöktes, även om inga händelseprenumeranter var kopplade. UX-kontroller fungerar fortfarande korrekt, även om det inte finns några prenumeranter som lyssnar på händelserna. Båda använder design baserat på händelser.

Returvärden kräver ombud

Ett annat övervägande är den metodprototyp som du vill använda för ombudsmetoden. Som du såg har alla delegater som används för händelser en void returtyp. Det finns idiom för att skapa händelsehanterare som skickar information tillbaka till händelsekällor genom att ändra egenskaperna för händelseargumentobjektet. Även om dessa idiom fungerar är de inte lika naturliga som att returnera ett värde från en metod.

Observera att dessa två heuristiker ofta båda kan finnas: Om ombudsmetoden returnerar ett värde påverkar den algoritmen på något sätt.

Händelser har privat anrop

Andra klasser än den där en händelse finns kan bara lägga till och ta bort händelselyssnare. endast klassen som innehåller händelsen kan anropa händelsen. Händelser är vanligtvis offentliga klassmedlemmar. I jämförelse skickas delegeringar ofta som parametrar och lagras som privata klassmedlemmar, om de lagras alls.

Händelselyssnare har ofta längre livslängd

Den längre livslängden för händelselyssnare är en något svagare motivering. Du kan dock upptäcka att händelsebaserade designer är mer naturliga när händelsekällan utlöser händelser under en lång tidsperiod. Du kan se exempel på händelsebaserad design för UX-kontroller på många system. När du prenumererar på en händelse kan händelsekällan skapa händelser under programmets livslängd. (Du kan avbryta prenumerationen på händelser när du inte längre behöver dem.)

Jämför det med många ombudsbaserade design, där ett ombud används som argument till en metod, och ombudet används inte när metoden returneras.

Utvärdera noggrant

Ovanstående överväganden är inte hårda och snabba regler. I stället representerar de vägledning som kan hjälpa dig att avgöra vilket val som är bäst för din specifika användning. Eftersom de liknar dem kan du till och med skapa prototyper för båda, och överväga vilket som skulle vara mer naturligt att arbeta med. Båda hanterar sena bindningsscenarier väl. Använd den som förmedlar din design på bästa sätt.