Um die Unterschiede zu verstehen, können Sie sich diese beiden Beispiele ansehen
Beispiel mit Delegierten (Aktion in diesem Fall, bei der es sich um eine Art Delegat handelt, der keinen Wert zurückgibt)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
Um den Delegaten zu verwenden, sollten Sie so etwas tun
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
Dieser Code funktioniert gut, aber Sie könnten einige Schwachstellen haben.
Zum Beispiel, wenn ich das schreibe
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
Mit der letzten Codezeile hatte ich die vorherigen Verhaltensweisen überschrieben, nur mit einer fehlenden +
(ich habe +
statt verwendet +=
)
Eine weitere Schwachstelle ist, dass jede Klasse, die Ihre Animal
Klasse verwendet, RaiseEvent
nur einen Aufruf auslösen kann animal.RaiseEvent()
.
Um diese Schwachstellen zu vermeiden, können Sie events
in c # verwenden.
Ihre Tierklasse wird sich auf diese Weise ändern
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"));
}
}
Ereignisse aufrufen
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Unterschiede:
- Sie verwenden keine öffentliche Eigenschaft, sondern ein öffentliches Feld (bei Ereignissen schützt der Compiler Ihre Felder vor unerwünschtem Zugriff).
- Ereignisse können nicht direkt zugewiesen werden. In diesem Fall können Sie den vorherigen Fehler, den ich beim Überschreiben des Verhaltens gezeigt habe, nicht ausführen.
- Niemand außerhalb Ihrer Klasse kann das Ereignis auslösen.
- Ereignisse können in eine Schnittstellendeklaration aufgenommen werden, ein Feld jedoch nicht
Anmerkungen
EventHandler wird als folgender Delegat deklariert:
public delegate void EventHandler (object sender, EventArgs e)
Es werden ein Absender (vom Objekttyp) und Ereignisargumente benötigt. Der Absender ist null, wenn er aus statischen Methoden stammt.
Sie können EventHAndler
stattdessen auch dieses Beispiel verwendenEventHandler<ArgsSpecial>
siehe hier für die Dokumentation über Eventhandler