C# Programming

Image

デリゲートによる CallBack

開発環境: Visual Studio 2003 

1.目次

2.目的

デリゲートによるコールバックですが、書き方がめんどくさいと言うか、わかりにくいのでメモっておきます。

3.参考書

(1) 

4.通常のデリゲートによる呼び出しパターン

通常のデリゲート呼び出しパターンは、次のようになります。
Form1.cs がデリゲートの呼び出し側。
CallBackLib.cs がデリゲートで呼び出される側。

Form1.cs
using System;
....

namespace CallBack
{
        public class Form1
        {

        private void TestDelegate
        {            
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();
            // ClassLib のメソッド(ClassLibMethod)のデリゲートを作る。
            DelegForStr delegateForClassLibMethod = new DelegForStr(classLib.ClassLibMethod);
            // ClassLib のメソッドをデリゲートより呼び出す。
            string result = delegateForClassLibMethod("Hello ");
            // 結果を書く。
            Console.WriteLine(result);
        }
}
CallBackLib.cs
using System;

namespace CallBackLib
{
    public delegate string DelegForStr(string str);
    
        public class ClassLib
        {
                public ClassLib()
                {
                }
        
        public string ClassLibMethod(string str)
        {
            return str + "World";
        }
}

5.コールバックパターンその1(コールバックデリゲートを直接セットする)

コールバックを呼び出し側にセットして、コールバックしてもらう方法です。

動作は次のようになります。

Form1側が MyCallBack() へのデリゲートを CallBackLib のメンバー変数としてセットします。
Form1側が CallBackLib のメソッドAを呼び出します。
CallBackLib のメソッドAは、MyCallBack() へのデリゲートを呼び出す。
Form1の MyCallBack() が CallBackLib よりコールバックされる。

Form1.cs
using System;
....

namespace CallBack
{
        public class Form1
        {

        public void MyCallBack()
        {
            Console.WriteLine("MyCallBack has been called back!");
        }
        
        private void TestCallBack()
        {
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();

            // MyCallBack のデリゲートを作る。
            CallBackLib.CallBack myCallBack = new CallBackLib.CallBack(MyCallBack);   
        
            // ClassLib にコールバックをセットする。
            classLib.SetCallBack(myCallBack);

            // MyCallBack のデリゲートを引数として呼び出す。
            classLib.CallCallBack();               
        }
}
CallBackLib.cs
using System;

namespace CallBackLib
{
    public delegate void CallBack();
    
        public class ClassLib
        {
                public ClassLib()
                {
                }
        
        /// <summary>
        /// コールバックメンバー変数(パターン1用)
        /// </summary>
        private CallBack cb;

        /// <summary>
        /// コールバックをセットするメソッド(パターン1用)
        /// </summary>
        /// <param name="del"></param>
        public void SetCallBack(CallBack del)
        {
            cb = del;
        }

        /// <summary>
        /// セットしたコールバックを呼び出すメソッド(パターン1用)
        /// </summary>
        public void CallCallBack()
        {
            cb();
        }
}

6.コールバックパターンその2(コールバックデリゲートをデリゲートの引数で渡す)

デリゲートで、コールバックのデリゲートを渡して呼び出してもらうこともできます。

動作は次のようになります。

Form1側が MyCallBack() へのデリゲートを引数として、CallBackLib のデリゲートを呼び出す。
CallBackLib がデリゲートで呼び出される。
CallBackLib は、引数で渡されたMyCallBack() へのデリゲートを呼び出す。
Form1の MyCallBack() が CallBackLib よりコールバックされる。

Form1.cs
using System;
....

namespace CallBack
{
        public class Form1
        {

        public void MyCallBack()
        {
            Console.WriteLine("MyCallBack has been called back!");
        }
        
        private void TestCallBack()
        {
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();

            // MyCallBack のデリゲートを作る。
            CallBackLib.CallBack myCallBack = new CallBackLib.CallBack(MyCallBack);   
         
            // ClassLib のメソッド(CallBackCaller)のデリゲートを作る。
            DelegForCallBack delForCallBack = new DelegForCallBack(classLib.CallBackCaller);

            // MyCallBack のデリゲートを引数として呼び出す。
            delForCallBack(myCallBack);        
        }
}
CallBackLib.cs
using System;

namespace CallBackLib
{
    public delegate void CallBack();
    public delegate void DelegForCallBack(CallBack del);
    
        public class ClassLib
        {
                public ClassLib()
                {
                }
        

        /// <summary>
        /// コールバックの呼び出しメソッド(パターン2用)
        /// </summary>
        /// <param name="del"></param>
        public void CallBackCaller(CallBack del)
        {
            del();
        }
}

7.ソースコード

変更履歴
2003/5/25  初版作成 V1.0

Form1.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using CallBackLib;

namespace CallBack
{
    /// <summary>
        /// Form1 の概要の説明です。
        /// </summary>
        public class Form1 : System.Windows.Forms.Form
        {
        private System.Windows.Forms.Button btnDelegateCallBack;
        private System.Windows.Forms.Button btnCallback;
        private System.Windows.Forms.Button btnDeleg;
                /// <summary>
                /// 必要なデザイナ変数です。
                /// </summary>
                private System.ComponentModel.Container components = null;

                public Form1()
                {
                        //
                        // Windows フォーム デザイナ サポートに必要です。
                        //
                        InitializeComponent();

                        //
                        // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
                        //
                }

                /// <summary>
                /// 使用されているリソースに後処理を実行します。
                /// </summary>
                protected override void Dispose( bool disposing )
                {
                        if( disposing )
                        {
                                if (components != null) 
                                {
                                        components.Dispose();
                                }
                        }
                        base.Dispose( disposing );
                }

                #region Windows Form Designer generated code
                /// <summary>
                /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
                /// コード エディタで変更しないでください。
                /// </summary>
                private void InitializeComponent()
                {
            this.btnDeleg = new System.Windows.Forms.Button();
            this.btnDelegateCallBack = new System.Windows.Forms.Button();
            this.btnCallback = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // btnDeleg
            // 
            this.btnDeleg.Location = new System.Drawing.Point(56, 48);
            this.btnDeleg.Name = "btnDeleg";
            this.btnDeleg.Size = new System.Drawing.Size(184, 23);
            this.btnDeleg.TabIndex = 0;
            this.btnDeleg.Text = "デリゲート呼び出し";
            this.btnDeleg.Click += new System.EventHandler(this.button1_Click);
            // 
            // btnCallback
            // 
            this.btnCallback.Location = new System.Drawing.Point(56, 112);
            this.btnCallback.Name = "btnCallback";
            this.btnCallback.Size = new System.Drawing.Size(192, 23);
            this.btnCallback.TabIndex = 2;
            this.btnCallback.Text = "デリゲートによるコールバック";
            this.btnCallback.Click += new System.EventHandler(this.btnCallback_Click);
            // 
            // btnDelegateCallBack
            // 
            this.btnDelegateCallBack.Location = new System.Drawing.Point(56, 168);
            this.btnDelegateCallBack.Name = "btnDelegateCallBack";
            this.btnDelegateCallBack.Size = new System.Drawing.Size(184, 23);
            this.btnDelegateCallBack.TabIndex = 1;
            this.btnDelegateCallBack.Text = "デリゲート→デリゲートコールバック";
            this.btnDelegateCallBack.Click += new System.EventHandler(this.btnDelegateCallBack_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.btnCallback,
                                                                          this.btnDelegateCallBack,
                                                                          this.btnDeleg});
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
                #endregion

                /// <summary>
                /// アプリケーションのメイン エントリ ポイントです。
                /// </summary>
                [STAThread]
                static void Main() 
                {
                        Application.Run(new Form1());
                }

        private void button1_Click(object sender, System.EventArgs e)
        {            
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();

            // ClassLib のメソッド(ClassLibMethod)のデリゲートを作る。
            DelegForStr delegateForClassLibMethod = new DelegForStr(classLib.ClassLibMethod);

            // ClassLib のメソッドをデリゲートより呼び出す。
            string result = delegateForClassLibMethod("Hello ");

            // 結果を書く。
            Console.WriteLine(result);
        }
        
        public void MyCallBack()
        {
            Console.WriteLine("MyCallBack has been called back!");
        }

        /// <summary>
        /// コールバックをセットする方法(パターン1)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCallback_Click(object sender, System.EventArgs e)
        {
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();

            // MyCallBack のデリゲートを作る。
            CallBackLib.CallBack myCallBack = new CallBackLib.CallBack(MyCallBack); 
          
            // ClassLib にコールバックをセットする。
            classLib.SetCallBack(myCallBack);

            // MyCallBack のデリゲートを引数として呼び出す。
            classLib.CallCallBack();               
        }
        
        /// <summary>
        /// コールバックメソッドをデリゲートのパラメータで渡す方法(パターン2)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDelegateCallBack_Click(object sender, System.EventArgs e)
        {
            // ClassLib のインスタンスを作る。  
            CallBackLib.ClassLib classLib = new CallBackLib.ClassLib();

            // MyCallBack のデリゲートを作る。
            CallBackLib.CallBack myCallBack = new CallBackLib.CallBack(MyCallBack); 
           
            // ClassLib のメソッド(CallBackCaller)のデリゲートを作る。
            DelegForCallBack delForCallBack = new DelegForCallBack(classLib.CallBackCaller);

            // MyCallBack のデリゲートを引数として呼び出す。
            delForCallBack(myCallBack);
        }
        }
}
CallBackLib.cs
using System;

namespace CallBackLib
{
    public delegate string DelegForStr(string str);
    public delegate void CallBack();
    public delegate void DelegForCallBack(CallBack del);
    
        public class ClassLib
        {
                public ClassLib()
                {
                }
        
        public string ClassLibMethod(string str)
        {
            return str + "World";
        }


        /// <summary>
        /// コールバックメンバー変数(パターン1用)
        /// </summary>
        private CallBack cb;

        /// <summary>
        /// コールバックをセットするメソッド(パターン1用)
        /// </summary>
        /// <param name="del"></param>
        public void SetCallBack(CallBack del)
        {
            cb = del;
        }

        /// <summary>
        /// セットしたコールバックを呼び出すメソッド(パターン1用)
        /// </summary>
        public void CallCallBack()
        {
            cb();
        }

        /// <summary>
        /// コールバックの呼び出しメソッド(パターン2用)
        /// </summary>
        /// <param name="del"></param>
        public void CallBackCaller(CallBack del)
        {
            del();
        }
        }
}