2017-12-03 4 views
1

Ich lese das Buch Under the hood of .NET memory management (veröffentlicht von Red-Gate). Sie können eine pdf version on their website finden.Event-Handler in Buch "Unter der Haube von .NET Memory Management"

Ich dachte, ich habe Event-Handler in Bezug auf die Referenzen zwischen Publishern und Abonnenten verstanden, aber die Erklärungen der Autoren zu Event-Handlern in Kapitel 5 "Anwendungsspezifische Probleme" (unter dem Titel "Windows Presentation Foundation") verwirrt mich.

Auf den Seiten 160-161 wird ein UI-Design beschrieben, das eine Master/Detail-Beziehung verwendet. Ich zitiere (Zahlen in eckigen Klammern sind Mine, um Referenzen für meine Fragen zu erstellen, pun nicht so sehr bestimmt):

Sie können mit einer Liste von Stammsätzen ein Gitter haben, und wenn Sie auf Ein Datensatz aus dem Master-Grid, ein neues Fenster öffnet sich mit den Details zu diesem Stammsatz. Wenn das Hauptfenster Ereignisse im Detailfenster [1] verdrahtet, dann kann das Detailfenster nicht bereinigt werden, bis die Ereignishandler im Hauptfenster ihre Referenzen auf das Detailfenster [2] freigeben. In diesem Fall ist das Detailfenster der Listener und das Masterfenster ist die Quelle [3]. In den meisten Fällen überlebt das Hauptfenster das Detailfenster, aber wenn die Ereignisbehandlungsroutinen nicht richtig behandelt werden, dann kann das Detailfenster nicht bereinigt werden, solange das Hauptfenster aktiv ist.

Detail.SomeEvent += new EventHandler(Master.SomeEvent_Handler); [4] 

[1] Dies ist sehr unklar Terminologie. Wer "verdrahtet" wer? Von diesem allein kann ich nicht bestimmen, wer der Zuhörer ist und wer der Abonnent ist (ich kann nur annehmen ...). Der nächste Satz [3] beantwortet scheinbar genau diese Frage, indem er sagt, dass der Master die Quelle und das Detail der Listener ist, aber erst, nachdem Verwirrung durch Angabe des genauen Gegenteils in [2] eingeführt wurde (weil das Ereignis Handler sind nicht im Hauptfenster).

Das Codebeispiel [4] entspricht auch nicht dem, was in [3] gesagt wird (entspricht aber [2]). Wenn das Hauptfenster die Quelle ist, dann sollte es sein:

Master.SomeEvent += new EventHandler(Detail.SomeEvent_Handler); [5] 

Richtig?

Abgesehen von all dieser Verwirrung verstehe ich Ereignishandler wie folgt. Wenn Master Ereignisse hat, auf die Detail subskribiert ist (wie in [5]), dann hat Master eine Referenz auf Detail (weil ein Verweis auf ein Löschen einer Instanz einen Verweis auf die Instanz erstellt, in diesem Fall Detail). Solange also Master lebt, wird Detail ebenfalls im Speicher gehalten, es sei denn, der Ereignishandler ist vom Ereignis abgekoppelt.

Sind meine Kritik am Buch und mein eigenes Verständnis korrekt?

Antwort

1

Es ist nie sehr offensichtlich aus der C# -Syntax Zucker. Ein Delegate-Konstruktor nimmt zwei Argumente unter der Haube. Die offensichtliche ist die Event-Handler-Methode. Der nicht-offensichtliche ist das Objekt, dessen Handler-Methode aufgerufen wird. Nicht offensichtlich, weil Sie es nie in den Code eingeben. Es ist this. Mit C# können Sie es nicht einmal angeben, andere Sprachen tun es.

So das Master-Objekt jetzt, wie eine Referenz auf das Detail-Objekt, notwendig, um die Event-Handler-Methode ordnungsgemäß aufzurufen.

Solange das Master-Objekt aktiv ist, wird das Detail-Objekt nicht erfasst. Es sei denn, Sie entfernen das Ereignis explizit erneut oder verwenden das schwache WPF-Ereignismuster. Oder, im Idealfall, entwerfe den Code so, dass die Objekte Master und Detail gleichzeitig sterben. Sie haben Ihnen ein Beispiel gegeben, wo das nicht einfach ist.

Es gibt andere Möglichkeiten, dies zu tun, die keine Ereignisse verwenden. Sie können eine IDetail-Schnittstelle mit Methoden deklarieren, die das Ereignis darstellen, das Sie auslösen möchten. Und geben Sie der Master-Klasse eine AddDetail (IDetail) und RemoveDetail (IDetail) -Methode. Jetzt ist die Speicherverwaltung kristallklar und es wird viel offensichtlicher, wenn Sie vergessen, RemoveDetail() aufzurufen. Die WPF-Entwickler bevorzugten jedoch stark die Verwendung von Ereignissen, sie mussten mit dem schwachen Ereignismuster kommen, um die Lecks in ihrem eigenen Objektmodell zu vermeiden.

+0

Was ist die Bedeutung des nicht offensichtlichen Parameters 'this'? Stellt es Kontext (wie in Javascript? (Entschuldigen Sie die Häresie))? Können Sie mich auf eine Dokumentation oder ein Buch hinweisen? Ich würde gerne mehr dazu lesen. – bvgheluwe

+0

Nichts besonders tief. Das Ereignis ruft eine Instanzmethode auf, es benötigt eine Objektreferenz. Der Delegierte speichert es. Notieren Sie die Delegate.Target-Eigenschaft. Es ist nicht einfach zu sehen, wie es einen Wert bekommt. –