Wenn Ereignisse als Delegierten in .NET implementiert sind, was ist der Punkt des .Event IL Abschnitts?

StackOverflow https://stackoverflow.com/questions/219815

Frage

Ich habe einige sehr gute Fragen auf Stack-Überlauf gesehen über die Delegierten, Ereignisse und die .NET-Implementierung dieser beiden Funktionen. Eine Frage, insbesondere „ Wie C # Ereignisse hinter den Kulissen arbeiten ? “, produziert eine große Antwort, die sehr gut einige subtile Punkte erklärt.

Die Antwort auf die obige Frage macht diesen Punkt:

  

Wenn Sie deklarieren eine feldartige Veranstaltung   ... erzeugt der Compiler die Methoden   und ein privater Bereich (des gleichen Typs   als Delegierten). Innerhalb der Klasse,   wenn Sie sich auf ElementAddedEvent   Sie beziehen sich auf das Feld. Draußen   die Klasse, Sie beziehen sich auf die   Feld

Ein MSDN-Artikel aus der gleichen Frage verknüpft ( " Feld wie Ereignisse ") fügt hinzu:

  

Der Begriff ein Ereignis zu erheben ist   genau äquivalent zu dem Aufruf   Delegieren von der Veranstaltung vertreten -   so gibt es keine spezielle Sprache   Konstrukte für die Ereignisse zu erhöhen.

weiter untersuchen Wanting, baute ich ein Testprojekt, um die IL zu sehen, dass ein Ereignis und ein Delegierter zusammengestellt werden:

public class TestClass
{
    public EventHandler handler;
    public event EventHandler FooEvent;

    public TestClass()
    { }
}

erwartete ich die Delegierten Feld handler und das Ereignis FooEvent zu etwa dem gleichen IL-Code zu kompilieren, mit einigen zusätzlichen Methoden Zugang zum Compiler generierte FooEvent Feld zu wickeln. Aber die IL erzeugt war nicht ganz das, was ich erwartet hatte:

.class public auto ansi beforefieldinit TestClass
    extends [mscorlib]System.Object
{
    .event [mscorlib]System.EventHandler FooEvent
    {
        .addon instance void TestClass::add_FooEvent(class [mscorlib]System.EventHandler)
        .removeon instance void TestClass::remove_FooEvent(class [mscorlib]System.EventHandler)
    }

    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        // Constructor IL hidden
    }

    .field private class [mscorlib]System.EventHandler FooEvent
    .field public class [mscorlib]System.EventHandler handler
}

Da Ereignisse nicht mehr als Delegierte mit Compiler generierten add und remove Methoden sind, ich hatte nicht erwartet, als etwas anderes als in IL behandelt Ereignisse zu sehen. Aber die Hinzufügen und Entfernen von Methoden in einem Abschnitt definiert sind, die .event beginnt, nicht .method als normale Methoden sind.

Meine letzten Fragen sind: wenn Ereignisse einfach als Delegierte mit Accessormethoden umgesetzt werden, was ist der Punkt, einen .event IL Abschnitt zu haben? Können sie nicht durch die Verwendung .method Abschnitte in IL, ohne dass dies umgesetzt werden? Ist .event entspricht .method?

War es hilfreich?

Lösung

Ich bin nicht sicher, dass überraschend ... Objekte vs Felder in die gleiche vergleichen (da Eigenschaften vor der gleichen Funktion wie die Ereignisse: Verkapselung über Accessoren):

.field public string Foo // public field
.property instance string Bar // public property
{
    .get instance string MyType::get_Bar()
    .set instance void MyType::set_Bar(string)
}

Auch - Veranstaltungen nicht erwähnt etwas über Felder; sie nur die Zugriffsmethoden definieren (Hinzufügen / Entfernen). Der Delegierten Backer ist ein Implementierungsdetail; es passiert einfach so, dass Feld-like-Ereignisse ein Feld als Trägerelement erklären - in der gleichen Art und Weise, die automatisch implementierte-Eigenschaften ein Feld als Trägerelement deklarieren. Andere Implementierungen sind möglich (und sehr häufig, vor allem in Formen usw.).

Andere gemeinsame Implementierungen:

Sparse-Ereignisse (Kontrollen, etc.) - Eventhandlerlist (oder ähnlich):

// only one instance field no matter how many events;
// very useful if we expect most events to be unsubscribed
private EventHandlerList events = new EventHandlerList();
protected EventHandlerList Events {
    get { return events; } // usually lazy
}

// this code repeated per event
private static readonly object FooEvent = new object();
public event EventHandler Foo
{
    add { Events.AddHandler(FooEvent, value); }
    remove { Events.RemoveHandler(FooEvent, value); }
}
protected virtual void OnFoo()
{
    EventHandler handler = Events[FooEvent] as EventHandler;
    if (handler != null) handler(this, EventArgs.Empty);
}

(die oben ist ziemlich viel das Rückgrat der Win-Formen Ereignisse)

Fassade (obwohl dies verwirrt den „Absender“ ein wenig, einige Vermittler Code ist oft hilfreich):

private Bar wrappedObject; // via ctor
public event EventHandler SomeEvent
{
    add { wrappedObject.SomeOtherEvent += value; }
    remove { wrappedObject.SomeOtherEvent -= value; }
}

(die oben kann auch verwendet werden, um effektiv ein Ereignis zu umbenennen)

Andere Tipps

Veranstaltungen sind nicht die gleichen wie die Delegierten. Events kapseln das Hinzufügen / einen Handler für ein Ereignis zu entfernen. Die Prozedur wird mit einem Delegierten vertreten.

Sie könnte nur AddClickHandler / RemoveClickHandler usw. für jede Veranstaltung schreiben - aber es wäre relativ schmerzhaft sein, und wäre es nicht für Werkzeuge wie VS leicht machen Ereignisse trennen von alles andere.

Die

ist wie Eigenschaften wirklich - man könnte GetSize schreiben / SetSize etc (wie Sie in Java zu tun), sondern durch Eigenschaften abscheidet, gibt es syntaktische Verknüpfungen zur Verfügung und bessere Werkzeugunterstützung

.

Punkt Ereignisse aufweisen, die ein Paar von hinzufügen, entfernen, Methoden sind Einkapselung .

Die meisten der Zeitereignisse werden verwendet, wie sie ist, aber auch andere Zeiten Sie nicht wollen, die Delegierten auf das Ereignis in einem Feld angebracht speichern, oder möchten Sie zusätzliche Verarbeitung auf Add tun oder Ereignismethoden entfernen.

Zum Beispiel einer Möglichkeit, speichereffiziente Ereignisse zu implementieren die Delegierten in einem Wörterbuch zu speichern, anstatt ein privates Feld, weil Felder immer zugewiesen werden, während ein Wörterbuch wächst nur in der Größe, wenn Elemente hinzugefügt werden. Dieses Modell ist ähnlich mit dem, was WinForms und WPF verwendet make effiziente Nutzung von Speicher (WinForms und WPF verwendet Schlüssel Wörterbücher speichern Delegierten nicht Listen)

machen
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top