C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

イベントハンドラの -= が必須な場合は?

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■84957 / inTopicNo.1)  イベントハンドラの -= が必須な場合は?
  
□投稿者/ ぶなっぷ (121回)-(2017/08/26(Sat) 08:55:51)

分類:[.NET 全般] 

C#にて、WPFによるプログラミングを行っています。
自作イベントのイベントハンドラを += で追加していますが、
 -= が必須な場合と、そうでない場合がの切り分けがよく分かりません。

今のところ、私の認識は以下のようなものです。

public class TestDlg : Window
{
    private event EventHandler TestEvent;

    private vid Loaded(object sender, RoutedEventArgs e)
    {
        TestEvent += TestEventHandler;
    }

    private void TestEventHandler(object sender, EventArgs e)
    {
        Refresh();
    }
}
のように、ロード時にイベントハンドラを += で登録するものとすると、

TestDlg を new した後で、Loaded()が一度しか呼ばれないなら、
ガベージコレクタに任せれば良く、-= はいらない。

TestDlg を new した後で、ShowDialog() を何度も呼び出すなど、
同一インスタンスで、Loaded()が複数回走るなら、-= しないと、
どんどんイベントハンドラが貯まっていく。

この認識で良いのでしょうか?

引用返信 編集キー/
■84958 / inTopicNo.2)  Re[1]: イベントハンドラの -= が必須な場合は?
□投稿者/ Azulean (853回)-(2017/08/26(Sat) 09:50:56)
2017/08/26(Sat) 09:52:11 編集(投稿者)

No84957 (ぶなっぷ さん) に返信
> 自作イベントのイベントハンドラを += で追加していますが、
> -= が必須な場合と、そうでない場合がの切り分けがよく分かりません。
>

最近、MSDN フォーラムで似たような話があったので参考になるかもしれません。
https://social.msdn.microsoft.com/Forums/ja-JP/74a98fb4-e598-4121-8927-ef57b9aaff89/-new-new-?forum=csharpgeneralja

> TestDlg を new した後で、Loaded()が一度しか呼ばれないなら、
> ガベージコレクタに任せれば良く、-= はいらない。
(略)
> この認識で良いのでしょうか?

合っていると思います。
ただ、個人で作るのではなく、チームで作るのであれば、使い方の間違い(想定外の利用方法)のリスクを減らすため、対処しておくと言うこともあり得ます。

主に気にするのは「イベントハンドラのあるオブジェクトと、イベントを提供するオブジェクトの寿命の差」「イベントハンドラを設定するトリガーの発生回数」「イベントを監視すべき区間の長短」でしょうか。

たとえば、Button1_Click で処理している間だけイベントを知りたいなら、そのメソッド内で -= は必要となりますので。
結局、「必須」とはプログラムを書く人の考え・好みや、プログラムの構造によって変わるので、「この場合は必須です」といえるものはないかと思います。
引用返信 編集キー/
■84959 / inTopicNo.3)  Re[2]: イベントハンドラの -= が必須な場合は?
□投稿者/ ぶなっぷ (122回)-(2017/08/26(Sat) 09:55:01)
Azuleanさん、ありがとうございます。

であれば、もう一つ質問で申し訳ないのですが、

XAMLのコンパイル時には、
IComponentConnectorインターフェースを利用して、
同一インスタンスで、Loaded()が複数回走る場合でも -= が不要なように
実装されています(*.g.i.csのコードを参照)。
(実際に、テストしてみてもイベントハンドラが貯まることはなかった)

この仕組みを(g.i.csではなく)自身のコード中で簡単に利用できる方法は
ないのでしょうか?

よろしくお願いいたします。

引用返信 編集キー/
■84960 / inTopicNo.4)  Re[3]: イベントハンドラの -= が必須な場合は?
□投稿者/ Azulean (854回)-(2017/08/26(Sat) 16:14:24)
2017/08/26(Sat) 16:16:23 編集(投稿者)

No84959 (ぶなっぷ さん) に返信
> この仕組みを(g.i.csではなく)自身のコード中で簡単に利用できる方法は
> ないのでしょうか?

こだわりがないならこういったコードでも良いですけどね。

TestEvent -= TestEventHandler;
TestEvent += TestEventHandler;

1 行目は未登録なら何もしない、登録済みなら登録解除となるので、1 度目は何もしない、2 度目以降はその直前に登録したイベントハンドラを解除することになります。

_handlerAdded みたいなフラグ管理でも良いと思います。
登録するイベント数が多い場合はフラグ管理の方が行数少なくて良さそうです。
(-= を書くのはわかる人はわかるというものなので、コードの意味を明示するという意味では、フラグ管理の方がわかりやすいかも?)
引用返信 編集キー/
■84961 / inTopicNo.5)  Re[4]: イベントハンドラの -= が必須な場合は?
□投稿者/ ぶなっぷ (123回)-(2017/08/28(Mon) 09:22:16)
2017/08/28(Mon) 09:22:36 編集(投稿者)
Azuleanさん、ありがとうございます。

こちらでも、いろいろ調査してみましたが、
やはり、Azuleanさんのおっしゃっている方法が良さそうです。
それでいきたいと思います。

ただ、なんとなく疑問なのが、
 += で追加する際に、Dictionaryのように重複キー追加時は上書きとなる
ようにしなかったんだろう?ということです(^^;
そうすれば、イベントハンドラが貯まっていくこともない。

いずれにせよ、元の疑問については解決しましたので、クローズさせていただきます。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ