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

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

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

Re[3]: イベント削除方法


(過去ログ 130 を表示中)

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

■76989 / inTopicNo.1)  イベント削除方法
  
□投稿者/ kiku (57回)-(2015/09/03(Thu) 15:37:39)

分類:[C#] 

開発環境
 WindowsFormアプリ
 VS2010
 C#

質問
 イベント削除時に良くその1のようなソースを見かけます。
 これは間違えで、その2のようなソースにすべきと
 考えているのですが、正しいのでしょうか?
 それともどちらでもきちんとイベント削除ができるのでしょうか?

その1
button1.Click += new System.EventHandler(this.button1_Click);
button1.Click -= new System.EventHandler(this.button1_Click);

その2
System.EventHandler event = new System.EventHandler(this.button1_Click);
button1.Click += event;
button1.Click -= event;

引用返信 編集キー/
■76990 / inTopicNo.2)  Re[1]: イベント削除方法
□投稿者/ Hongliang (339回)-(2015/09/03(Thu) 15:40:12)
>  イベント削除時に良くその1のようなソースを見かけます。
>  これは間違えで、その2のようなソースにすべきと
>  考えているのですが、正しいのでしょうか?
>  それともどちらでもきちんとイベント削除ができるのでしょうか?
どちらでも問題ありません。
同じメソッド(のリスト)を持つデリゲートインスタンスは同一の物として扱われます。
引用返信 編集キー/
■76991 / inTopicNo.3)  Re[1]: イベント削除方法
□投稿者/ 魔界の仮面弁士 (480回)-(2015/09/03(Thu) 16:01:52)
No76989 (kiku さん) に返信
>  それともどちらでもきちんとイベント削除ができるのでしょうか?
『event』は予約語なので、変数名として使うとコンパイルエラーになります。
その意味においては、少なくとも2では削除できません。

予約語を変数名として使いたい場合には、先頭に @ を付与します。

System.EventHandler @event = new System.EventHandler(this.button1_Click);
button1.Click += @event;
button1.Click -= @event;


それはさておき、イベントの削除としてはどちらでも OK です。
引用返信 編集キー/
■76992 / inTopicNo.4)  Re[2]: イベント削除方法
□投稿者/ kiku (58回)-(2015/09/03(Thu) 16:32:31)
Hongliangさん、魔界の仮面弁士さん

ご回答ありがとうございます。
すっきりしました。


魔界の仮面弁士さん

> 『event』は予約語なので、変数名として使うとコンパイルエラーになります。
ご指摘部分はごもっともで恥ずかしい。

解決済み
引用返信 編集キー/
■76999 / inTopicNo.5)  Re[3]: イベント削除方法
□投稿者/ 魔界の仮面弁士 (483回)-(2015/09/03(Thu) 17:59:55)
No76992 (kiku さん) に返信
> ご回答ありがとうございます。
> すっきりしました。

ただし、『ラムダ式』や『匿名メソッド』を使う場合は注意して下さい。

この場合、「その1」の「 button1.Click -= delegate { … }; 」な手法では
解除できませんので、「その2」のようにデリゲート変数に保持しておき、
そのインスタンスを通じて -= する必要があります。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

class Program
{
    static void Baz() { Console.WriteLine("Baz"); }

    static void Main(string[] args)
    {
        var foo = new Action(Baz);
        var bar = new Action(Baz);

        Action x = delegate { };
        Action y = delegate { };


        // foo と bar は別のインスタンスだが、
        // 参照しているメソッドは同一インスタンス
        Console.WriteLine("foo is bar = " + ReferenceEquals(foo, bar));
        Console.WriteLine("foo.Method is bar.Method = " + ReferenceEquals(foo.Method, bar.Method));

        Console.WriteLine("x is y = " + ReferenceEquals(foo, bar));
        Console.WriteLine("x.Method is y.Method = " + ReferenceEquals(x.Method, y.Method));


        Console.WriteLine("==> 一回目 (未割当) ****");
        Console.WriteLine("== 一回目のイベント呼びだし");
        RaiseEvents();  // 無反応
        Console.WriteLine("<===");

        Console.WriteLine("==> 二回目 (割当) ****");
        Sample += foo;      // foo のみ登録
        //Sample += bar;
        Sample += new Action(delegate { Console.WriteLine("匿名メソッド"); });
        Sample += () => { Console.WriteLine("ラムダ式"); };
        Console.WriteLine("== 二回目のイベント呼びだし");
        RaiseEvents();  // 登録した 3 つのハンドラが呼ばれる
        Console.WriteLine("<===");

        Console.WriteLine("==> 三回目 (解除) ****");
        //Sample -= foo;
        Sample -= bar;      // foo ではなく bar を解除してみる
        Sample -= new Action(delegate { Console.WriteLine("匿名メソッド"); });
        Sample -= () => { Console.WriteLine("ラムダ式"); };
        Console.WriteLine("== 三回目のイベント呼びだし");
        RaiseEvents();  // Baz は解除されたが、匿名メソッドやラムダ式は解除されない
        Console.WriteLine("<===");

        Console.WriteLine("おしまい ****");
        Console.Read();
    }


#if CUSTOM_EVENT_TEST
    static EventHandlerList delegates = new EventHandlerList();
    static event Action Sample
    {
        add { delegates.AddHandler("SampleEvent", value);  }
        remove { delegates.RemoveHandler("SampleEvent", value); }
    }
    static void RaiseEvents()
    {
        Delegate ev = delegates["SampleEvent"];
        if(ev != null) ev.DynamicInvoke();
    }
#else
    static event Action Sample;
    static void RaiseEvents()
    {
        if (Sample != null) Sample.Invoke();
    }
#endif
}

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


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -