C#

[C#] イベントハンドラを基本から使いこなす!

こんにちは、リバティエンジニア[?]のFUNAです。 現役エンジニアとしてアプリケーション開発やWeb制作、SEOやブログ運営をしています。

突然ですが、「イベントハンドラ」ってご存知ですか?

例えば、C#で配置したボタンコントロールがクリックされた時に処理したい事がある時には、このボタンの「クリックイベント」というのに処理を紐づける事で実装する事ができます。

ポイント

実はこのイベントハンドラは「デリゲート」で実装されています。

デリゲートについては下の記事を参考にしてみてください。

>> C# 世界一わかるデリゲート(delegate)について

今回はそのイベントハンドラを使いこなすことにより、期待した場所で期待した動作を正しく実装する方法を覚えてもらえればと思います。

では早速見ていきましょう!



私は現役でフリーランスエンジニアとしてWebサービスやサイト制作をしながら、現在ご覧いただいているブログの運営をしております。

C# イベントハンドラとは?

先ほども少しだけ説明しましたが、まずは「イベントハンドラ」とは何か?ということを簡単に説明したいと思います。

イベントハンドラとは、特定のイベントが発生した際に行う"処理"のことです。

イベントハンドラに処理を渡すときは、先程少しだけお話した”デリゲート”を渡してやります。
そうすることで、そのイベントが発生したときに、デリゲートで渡した処理が勝手に走ってくれます。

C# イベントハンドラの仕組み

では次にイベントハンドラの仕組みについてですが、「なぜ、イベントハンドラにデリゲートを渡すと勝手に処理してくれるのか?」

このような疑問を持つ方が少なからずいると思います。

なぜ、イベントハンドラにデリゲートを渡すと勝手に処理してくれるのか?

それを知るにはまず、イベントハンドラについて少しだけ知る必要があります。
イベントハンドラの定義を見てみましょう。

普段何気なく使っている標準関数などの定義を見てみると新しい発見などがあって、楽しいですよ♪

 

// イベントハンドラの定義
delegate void EventHandler(object snder, EventAgrs e);

この定義を見てみるとわかるのですが、イベントハンドラは”デリゲート”なんです。

VisualStudioなんかの統合開発環境でアプリケーションなどの開発をしている方はイベントの記述について詳しく見たことがない方もいるかもしれません。
便利すぎてそれでも開発できてしまうんです。

「そんなの常識!知ってるに決まっている!」 という方は先ほどの私の発言は忘れてください。。

少し話がずれましたが、本題に戻りましょう。

ポイント

デリゲートは、「同じ戻り値の型で同じ引数の型を持つメソッドを代入できる」

なので、イベントハンドラと同じ型の関数を作って、それを代入すればイベント発生時にその処理を実行してくれるというわけなんです。

イベントハンドラに処理を追加するサンプルコード

文字ばかり読んでもしっくりこないと思うので、一番シンプルな例文をご紹介します!

namespace WindowsFormsApplication
{
    public partial class Form1 : Form 
    {
        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Form1()
        {
            InitializeComponent();
            // フォームクローズイベントに、Form1_FormClosedメソッドの処理を追加
            FormClosed += new FormClosedEventHandler(Form1_FormClosed);
        }
        /// <summary>
        /// フォームが閉じたら確認のダイアログを表示します。
        /// </summary>
        /// <param name="sender">オブジェクト</param>
        /// <param name="e">イベント</param>
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            MessageBox.Show("フォームのClosedイベント");
        }
    }
}

どうでしょうか。
正直普通にプログラムを組んでいる分には上記のやり方でイベントを追加する。ぐらいの理解で良いと思います。

イベントに登録した関数にある引数
(object sender, FormClosedEventArgs e)
これって何ですか?

やはり気になりますよね!みなさん一度はこの疑問に気が付きますが、意外と理解できていない人が多いんです。
なので、今日覚えてしまってください♪

C#のイベントハンドラなどの引数にある「object sender」とは?

イベントハンドラなどの引数にある「object sender」とはなんだ?と疑問に思う方も多いと思います。

MSDN公式ドキュメントで見てみると、「イベントのソース」や「イベントを発生させるインスタンスを参照します」と記載があります。

.....わからないですよね。

ポイント

簡単に言うと、「イベントの発生元のコントロールオブジェクト」が格納されています。

例えば、ボタンクリックイベントが発生した場合、発生元のボタンコントロールが入ります。

フォームクローズイベントが発生した場合、発生元のフォームコントロールが入ります。

/// <summary>
/// TestButtonのクリックイベント
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TestButton_Click(object sender, EventArgs e)
{
    // ボタンクリック時の処理
    // sender にはこのイベントが発生した元のButtonコントロールが入っています。
}

EventArgs e とは?

こちらもMSDNで見てみると、「イベント データを格納している」や「型 EventArgs から派生し、イベント データを保持します」と記載があります。

MSDNって公式なので正確な情報源なのですが、言葉が難しいですよね。。

つまり、この「EventArgs e」にはイベントの情報が入っています。

発生したイベントが、EventArgsクラスを継承したクラスのインスタンスが入っています。

これについては今回はそれほど詳しく説明しません。

ポイント

”イベントクラスのインスタンス”が入っている。と覚えておいて下さい。

まとめ

今回はイベントハンドラについて解説しました。

押さえておいてほしい点としては、

ポイント

・デリゲートは同じ戻り値の型/同じ引数の型を持つメソッドを代入できる
・イベントハンドラとはデリゲートの一種でありイベントが発生した時に行う処理
・引数の一つ目にはイベントの発生元コントロールが入っている
・引数の二つ目には、発生したイベントの情報が入り、その情報というのはEventArgsクラスを継承したクラスのインスタンスである

ということです。

VisualStudioなんかを使っていると、イベントのコードは自動生成されるので、'なんとなく'でイベント処理を実装していることが多くなってしまいます。

いつかイベントについてトリッキーな実装をする時が来ると思いますので、その時はまたこの記事を参考にしてみてください!

今回のイベント関連で他にも役に立つ記事があるので、良ければ見ていってください。

>> [C#] Windows.Formsのイベントが発生する順番は?

>> C# コントロールのイベントを一時的に無効化する方法

>> 【結論】未経験でプログラミングの独学はぜんぜん可能

 

Copyright© FUNA BLOG , 2020 All Rights Reserved.