[C#][WPF]学習メモ(その1)~イベント~

業務ツール作成にC#を触り始めたので、学習した内容をひとまずスクラップしていきます。

イベント

C言語に無い概念として、イベントがあります。

イベント発生側がイベントを受け取ったら割り込みが発生し、対応するイベントハンダラを呼び出すという仕組み。

参考URL:

  1. https://ufcpp.net/study/csharp/sp_event.html
  2. https://qiita.com/laughter/items/e9cf666e0430acc39e95
  3. https://qiita.com/Ich_wei_/items/1e5993c316f4a78fac79
  4. https://dobon.net/vb/dotnet/vb2cs/event.html

イベント型のクラスには、イベントハンダラ型のデリゲートが定義されていいます。
初期状態では、処理も関数ポインタも入っていない状態です。
これに対して、+=や-=などの演算子を用いてイベントハンダラを入れてやると
イベント発生に応じて処理を行わせることができます。

デリゲートの引数としては、(sender,  EventArgs)が定義されていることが多いです。
Senderは、イベントの発生元のオブジェクト、EventArgsはイベントの内容が格納されていることが多いです。

イベントを使って任意のメッセージは送れるの?

では、自前のメッセージをEventArgsに入れて送れそうに思えてきます。
しかし、EventArgsのメンバには直接触れそうなstring型が無いように思います。
では、どうすればいいかというと、下記に示すように自前のEventArgsを用意すればいいです。

public class ErrorEventArgs : EventArgs
{
    public string message;
}

上記では、EventArgsクラスを継承したErrorEventArgsクラスを定義しています。
クラスのメンバとして、string型のmessageを追加してやることで、
任意の文字列を格納してイベントハンダラに送ることができます。
試してませんが、型を変えれば何でも送れそうですね。

でも、このままではErrorEventArgs形を引数に持つことができる
イベントやイベントハンダラは存在しないため使い道がありません。

自前のメッセージを送れるイベントを定義してしまえ

なので、下記のように仕込みます。

//イベントを発生させる側
class ChildClass{
//省略
    public event ErrorEventHandler errorEvent; //イベントの定義

    ErrorEventArgs e = new ErrorEventArgs(); 
    e.message = "Hello Event!"; //自前のEventArgsにメッセージを仕込む
    errorEvent(this, e); //イベント発生
}

//イベントを受け取る側
class ParentClass{
//省略
    public delegate void ErrorEventHandler(object sender, ErrorEventArgs e);//デリゲートの宣言
    private ChildClass childClass = null; //ChildClassのインスタンス

    public ParentClass{ //コンストラクタ
        childClass = new ChildClass();
        childClass.errorEvent += new ErrorEventHandler(errorHandler);
    }

    private void errorHandler(sender object, ErrorEventArgs e){
        MessageBox.Show(e.message); //仕込んだメッセージを表示する。
    }

※必要なusingや、処理などは補完しながら読んでください

さて、ここまで見ると結局デリゲートと何が違うの?って感じです。
答えは、外部のクラスから保護されている(?)デリゲートがイベントの本質とのことです。
例えば、イベントのデリゲート代入の部分は+=や-=を使うのです。(=だとエラー)。

今回のコードにはNullReferenceExceptionを発生させるバグが潜んでいますので、
イベント初期化時のデリゲートには”何もしない”処理を格納しておくのが無難です。

デリゲートが何かわからない状態からスタートして、ここまで紆余曲折ありましたが
何とか理解できてきたように思います。

関連記事:

[C#][WPF]学習メモ(その3)~シリアル通信~
[C#][WPF]学習メモ(その2)~タイマ~

コメント

Japanese
タイトルとURLをコピーしました