37

イベントをリッスンする場合は、次のように言います。

Subject.NewEvent += delegate(object sender, NewEventArgs e)
{
    //some code
}); 

このイベントの登録を解除するにはどうすればよいですか? それとも、メモリがリークするのを許しますか?

4

7 に答える 7

43

匿名デリゲートのインスタンスに名前を付けます。

EventHandler<NewEventArg> handler = delegate(object sender, NewEventArgs e)
{
    //some code
};

Subject.NewEvent += handler;
Subject.NewEvent -= handler;
于 2009-08-28T16:40:05.343 に答える
25

イベントの登録を解除する必要がある場合は、イベント ハンドラーの匿名デリゲートを避けることをお勧めします。

これは、これをローカル メソッドに割り当てた方がよいケースの 1 つです。イベントから完全にサブスクライブを解除できます。

于 2009-08-28T16:38:35.830 に答える
22

最初の呼び出しでハンドラーを削除するには:

//SubjectType Subject = ..... already defined if using (2)

EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
    // (1)
    (sender as SubjectType).NewEvent -= handler;
    // or
    // (2) Subject.NewEvent -= handler;

    // do stuff here
};

Subject.NewEvent += handler;
于 2010-05-26T18:34:45.893 に答える
6

イベントのすべてのリスナーから登録を解除するためのメソッドを作成できます。これはまさにあなたが望むものではありませんが、役立つ場合があります。例(これは実際に機能します=)):

    class Program {
    static void Main(string[] args) {
        A someClass = new A();
        someClass.SomeEvent += delegate(object sender, EventArgs e) {
            throw new NotImplementedException();
        };

        someClass.ClearEventHandlers();
        someClass.FireEvent();

        Console.WriteLine("No error.");
    }

    public class A {
        public event EventHandler SomeEvent;

        public void ClearEventHandlers() {
            Delegate[] delegates = SomeEvent.GetInvocationList();
            foreach (Delegate delegate in delegates) {
                SomeEvent -= (EventHandler) delegate;
            }
        }

        public void FireEvent() {
            if (SomeEvent != null) {
                SomeEvent(null, null);
            }
        }
    }
}
于 2009-08-28T16:48:23.160 に答える
2

匿名関数の名前が必要であり、その名前がスコープ内にある場合にのみ実行できます。

    var handler = new EventHandler(delegate(object o, EventArgs e)
    {
        //do something...
    };

    Subject.NewEvent += handler;

    // later on while handler is still in scope...

    Subject.NewEvent -= handler;
于 2009-08-28T16:50:53.420 に答える
0

漏洩以外の理由で登録を抹消する必要がありますか?

「または単にメモリのリークを許可する」ビットに関しては、Subject がガベージ コレクターによってクリーンアップされるときに、匿名デリゲートも同様にクリーンアップされる必要があるため、リークは発生しません。

于 2009-08-28T16:37:18.580 に答える
0

いくつかの(あまりにも多くの)詳細でこれに入る(私の)別の質問があります:lambdas で使用するための弱いイベントハンドラーモデル

しかし、Reactive Frameworkが出てきた今、このような状況で真剣に検討したいと思います。

于 2010-09-15T11:57:00.700 に答える