Ich habe folgende Klasse:
%Vor%Ich habe eine Weile gesucht und es scheint, dass ein mit dem Schlüsselwort ref übergebenes Argument nicht gespeichert werden kann. Der Versuch, das Quellenargument zu einer Liste hinzuzufügen oder einer Feldvariablen zuzuweisen, erlaubt es nicht, einen Verweis auf die ursprüngliche Referenz des Delegaten beizubehalten. also meine Fragen sind:
Danke.
BEARBEITEN: Es scheint, dass ohne das Verwenden eines Wrappers oder einer Reflektion keine Lösung für das gegebene Problem existiert. Meine Absicht war, die Klasse so portabel wie möglich zu machen, ohne Delegierte in Hilfsklassen einzubinden. Danke allen für die Beiträge.
Bearbeiten : Ok, das war eine schlechte Idee, also zurück zu den Grundlagen:
Ich empfehle das Erstellen einer Wrapper-Klasse über eine Aktion:
%Vor%Und Umstrukturierung Ihrer ursprünglichen Klasse, um mit Wrappern zu arbeiten:
%Vor%Jetzt sollten Sie die gewünschten Ergebnisse erhalten.
Ich würde vorschlagen, dass die Subscription-Methode eine Implementierung einer SubscriptionHelper-Klasse zurückgeben sollte, die IDisposable implementiert. Eine einfache Implementierung wäre, dass SubscriptionHelper einen Verweis auf die Subskriptionsliste und eine Kopie des Subskriptionsdelegaten enthält. Die Subskriptionsliste selbst wäre eine List & lt; SubscriptionHelper & gt; und die Dispose-Methode für SubscriptionHelper würde sich selbst aus der Liste entfernen. Beachten Sie, dass jedes Abonnement einen anderen SubscriptionHelper zurückgibt, wenn derselbe Delegat mehrmals abonniert wird. Das Aufrufen von Dispose auf einem SubscriptionHelper bricht das Abonnement ab, für das es zurückgegeben wurde.
Solch ein Ansatz wäre viel sauberer als die Delegate.Combine / Delegate.Remove-Methode, die vom normalen .net-Muster verwendet wird, deren Semantik sehr merkwürdig werden kann, wenn ein Versuch unternommen wird, Delegierte mit mehreren Zielen zu abonnieren und abzubestellen.
BEARBEITEN:
Ja, meine schlechten - Delegaten sind unveränderliche Typen, also wird das Hinzufügen einer Methode zu einer Aufrufliste tatsächlich eine neue Delegateninstanz erzeugen.
Was zu einer Antwort nein auf Ihre Frage führt. Um den Delegaten abzubestellen, müssen Sie die Methode Broadcast
aus der Aufrufliste des Stellvertreters entfernen. Dies bedeutet, dass ein neuer Delegat erstellt und dem ursprünglichen Feld oder der ursprünglichen Variablen zugewiesen wird. Sie können jedoch nicht auf das Original zugreifen, wenn Sie die Methode Subscribe
nicht mehr verwenden. Außerdem kann es andere Kopien des ursprünglichen Feldes / der Original-Variable geben, die Ihre Methode in der Aufrufliste haben. Und es gibt keine Möglichkeit für Sie, alle zu kennen und ihre Werte zu ändern.
Ich würde vorschlagen, eine Schnittstelle zu dem Ereignis für Ihren Zweck zu deklarieren. Dies wird ein ziemlich flexibler Ansatz sein.
%Vor%Ursprüngliche Antwort
Gibt es einen bestimmten Grund, warum Sie source
delegate als ref
übergeben? Sie benötigen dies, wenn Sie beispielsweise einen anderen Delegaten von der Methode zurückgeben möchten.
Ansonsten ist der Delegat ein Referenztyp, also können Sie ihn abonnieren, ohne ihn als ref
...
Es ist ziemlich einfach, aber es gibt ein paar Fallstricke. Wenn Sie einen Verweis auf die Quellobjekte speichern, wie in den meisten Beispielen bisher vorgeschlagen, wird das Objekt nicht als Garbage Collection erfasst. Der beste Weg, dies zu vermeiden, ist eine WeakReference, die es dem GC ermöglicht, ordnungsgemäß zu arbeiten.
Alles, was Sie tun müssen, ist:
1) Fügen Sie der Klasse eine Quellenliste hinzu:
%Vor%2) Fügen Sie die Quelle zur Liste hinzu:
%Vor%3) Und dann implementieren Sie einfach entsorgen:
%Vor%Das heißt, es gibt auch die Frage, warum die Aktion als Referenz bestanden werden muss. Im aktuellen Code gibt es dafür keinen Grund. Wie auch immer, es hat keinen Einfluss auf das Problem oder die Lösung.
Vielleicht, statt zu versuchen, einen Verweis auf den Delegaten zu speichern, haben Sie, was Subskribenten ruft, den Verweis auf das Objekt mit dem Delegaten, um Aktionen für das Abonnement und die Abmeldung zu erstellen. Es ist ein zusätzlicher Parameter, aber es ist immer noch einfach.
%Vor%Und ein Beispiel abonnieren.
%Vor%Tags und Links c# parameters ref delegates unsubscribe