aby zrozumieć różnice, spójrz na te 2 przykłady
Przykład z delegatami (w tym przypadku akcja jest rodzajem delegata, który nie zwraca wartości)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
aby użyć delegata, powinieneś zrobić coś takiego
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
ten kod działa dobrze, ale możesz mieć słabe punkty.
Na przykład, jeśli to napiszę
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
z ostatnim wierszem kodu nadpisałem poprzednie zachowania tylko z brakującym jednym +
(użyłem +
zamiast +=
)
Innym słabym punktem jest to, że każda klasa, która używa twojej Animal
klasy, może podbić RaiseEvent
po prostu ją wywołując animal.RaiseEvent()
.
Aby uniknąć tych słabych punktów, możesz użyć events
w języku C #.
Twoja klasa zwierząt zmieni się w ten sposób
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
do wywoływania wydarzeń
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Różnice:
- Nie używasz właściwości publicznej, ale pola publicznego (ze zdarzeniami kompilator chroni twoje pola przed niepożądanym dostępem)
- Nie można bezpośrednio przypisywać wydarzeń. W takim przypadku nie możesz zrobić poprzedniego błędu, który pokazałem, zastępując zachowanie.
- Nikt spoza Twojej klasy nie może podnieść wydarzenia.
- Zdarzenia mogą być zawarte w deklaracji interfejsu, a pole nie
notatki
EventHandler jest zadeklarowany jako następujący delegat:
public delegate void EventHandler (object sender, EventArgs e)
pobiera nadawcę (typu Object) i argumenty zdarzenia. Nadawca ma wartość null, jeśli pochodzi z metod statycznych.
Możesz użyć również EventHAndler
zamiast tego przykładu, który używaEventHandler<ArgsSpecial>
patrz tutaj dla dokumentacji o EventHandler