C#でデリゲートメソッドを実装してイベント処理を共通化

画像に alt 属性が指定されていません。ファイル名: delegate-1971162_1920-1024x681.jpg

最近、ふとした思いから久々にC#を使って自分用のアプリケーションを作ってみようと思った際に、昔書いたコードを思い出して書いてみようというのが狙いです。

久々にC#で書いていると、イベント周りの処理を共通化したいなあと思うことが多々ありました。

そういえば、以前勤務していたシステム会社で使っていた処理があったはずと思いながら、なかなかネット上では参考になりそうな記事がありません。

うろ覚えながら実装してみたらうごいたので、いきなりですがデリゲートを用いたイベント処理の共通化についてご紹介いたします。

兄弟サイトからの移転記事となります。

デリゲートって何

デリゲート(delegate)とは、メソッドを参照するための型のことです。

メソッドを引数として渡して、処理を行うことができるようになります。

やりたいこと

デリゲートの実装の前に、 最終的 にどういう処理がやりたいか。
下に例を示します。

        /// <summary>
        /// ロード時
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
             //共通処理実行
            try
            {
                //共通前処理

                //イベントごとの処理

                //共通後処理
            }
            catch (Exception ex)
            {
                //エラー処理
                //ログ出力etc
            }
        }

よくあるのは、イベントごとの処理に対して、共通の前処理・後処理、エラー発生時のメッセージ表示やエラーログの出力などです。

ただ、これをロードやボタンクリック時にコピペで貼り付けるとなると、手間ですし、この一連の流れに変更があったときに、すべてのイベントを修正して回るという冗長なつくりになってしまいます。

そこで、共通部分を定義したメソッドに、各々の処理を渡して、一緒に実行してしまおうというわけです。

デリゲートの定義

メソッドを型として渡すために、デリゲートの定義をします。

ここでは、イベント発生時に引数として受け取る引数をそのまま次の処理に渡すために、下記のような引数をとるデリゲートを定義します。

protected delegate void delegateMethod(object sender, EventArgs e);

上記で定義したデリゲート型を用いてイベント処理を共通化したものが下記となります。

共通処理の実装

        protected void executeEvent(delegateMethod method, object sender, EventArgs e)
        {
            //共通処理実行
            try
            {
                //テスト
                Console.WriteLine("前処理");

                //メソッドの実行
                method.Invoke(sender, e);

                //テスト
                Console.WriteLine("後処理");
            }
            catch (Exception ex)
            {
                //エラー処理共通化
                MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

渡された

“method”という引数のメソッドを実行し、前後の処理を共通化することができます。

また、エラー発生時の処理を共通化することで、ソース記述者によるばらつきをなくし、ソースコードの記述量を減らすことができます。

使用例

実際の使用例は下記の通りです。

       /// <summary>
        /// 起動時イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            executeEvent(LoadForm, sender, e);
        }

        /// <summary>
        /// 起動時の処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadForm(object sender, EventArgs e)
        {
            //起動時の固有処理

        }

定義したイベント共通処理:executeEventに

メソッドとイベント発生時の引数を渡して、実行します。

まとめ・感想

共通化するというと、単にクラス化する、メソッドを分けるということを考えがちですが、メソッドそのものを渡すという考え方もあります。このあたりは、c++のポインタの概念がわかっていないとなかなか理解するのは厳しいかもしれません。

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