日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C#中委托、事件和回調的使用及說明_C#教程

作者:云無極 ? 更新時間: 2022-11-03 編程語言

委托是一個類,它定義了方法的類型,使得可以將方法當作另一個方法的參數來進行傳遞,這種將方法動態地賦給參數的做法,可以避免在程序中大量使用If-Else(Switch)語句,同時使得程序具有更好的可擴展性。

事件是對委托的封裝。如果不進行封裝,讓委托暴露給調用者,調用者就可以把委托變量重新引用到新的委托對象,也就刪除了當前要調用的方法列表;

定義一個事件有兩步,首先定義一個委托,它包括了這件事的“協議”和委托方法(由誰去做);其次,用event關鍵字和相關委托聲明這個事件。事件像是一個接口,封裝了委托所定的“協議”。由于委托已經定義了協議,剩下的就是按這個協議去辦事,至于怎么做它并不關心。調用者無法訪問委托對象。

回調函數就是把一個方法的傳給另外一個方法去執行。回調函數只是一個功能片段,由用戶按照回調函數的調用約定來實現的一個函數。可以把任意一個符合這個委托的方法傳遞進去,意思就是說這部分代碼是可變的。而設計上有一個抽離出可變部分代碼的原則,這種用法無疑可以用到那種場合了。從上可知,事件和回調都是對委托的一種用法。事件是把委托封裝起來,而回調函數則是由委托綁定不同的函數來實現不同的功能。

委托的使用案例

定義委托和方法

        //委托定義(要與方法中參數一致)
        public delegate int DelegateTest(int n1, int n2);
 
        class Math
        {
            //方法定義(委托要執行的方法,本案例把方案寫到class類中)
            public int Multiply(int n1, int n2)
            {
                return n1 * n2;
            }
 
            public int AddTest(int n1, int n2)
            {
                return n1 + n2;
            }
        }

委托的使用

        private void button1_Click(object sender, EventArgs e)
        {
            Math objMath = new Math();
 
            //創建委托對象
            DelegateTest delegateDemo1;
 
            //將方法與委托對象關聯起來 (委托:將方法當作另一個方法的參數來進行傳遞)
            //delegateDemo1 = new CallDelegate(objMath.Multiply);
            delegateDemo1 = objMath.Multiply; //與上面方法相同
            //delegateDemo1 += objMath.AddTest;  //給委托對象再綁定一個方法,若該條代碼執行,顯示結果為17
 
            //將委托實例化
            int result = delegateDemo1(5, 12);
            richTextBox1.AppendText(result.ToString() + "\r");
 
            //****委托的另外一寫法,通過Action或Func,如果有返回值用Func,否則用Action *****//
            //Func<int, int, int> func1 = new Func<int, int, int>(objMath.Multiply);
            Func<int, int, int> func1 = objMath.Multiply;
            richTextBox1.AppendText(func1.Invoke(6, 13) + "\r");
        }

執行的結果

利用Action或Func簡化代碼

        private void button4_Click(object sender, EventArgs e)
        {
            Math objMath = new Math();
            //委托的另外一寫法,通過Action或Func,如果有返回值用Func,否則用Action
            //Func<int, int, int> func1 = new Func<int, int, int>(objMath.Multiply); //同下
            Func<int, int, int> func1 = objMath.Multiply;
            richTextBox1.AppendText(func1.Invoke(6, 13) + "\r");
        }

事件的使用案例

        class ClassA
        {
            public string ClassAinfo = "A 默認!";
            public void DispInfo()
            {
                ClassAinfo = "A 收到!";
            }
        }
 
        class ClassB
        {
            public string ClassAinfo = "B 默認!";
            public void DispInfo()
            {
                ClassAinfo = "B 收到!";
            }
        }
        class DelegatEventTest
        {
            //定義委托
            public delegate void MyDelegateEventHandler();
            //定義事件
            public event MyDelegateEventHandler NotifyEveryOne;
            //調用事件
            public void Notify()
            {
                if (NotifyEveryOne != null)
                {
                    NotifyEveryOne();
                }
            }
        }

事件的使用

        private void button3_Click(object sender, EventArgs e)
        {
            //創建classA和classB的對象
            ClassA objA = new ClassA();
            ClassB objB = new ClassB();
            //創建委托的對象
            DelegatEventTest event1 = new DelegatEventTest();
 
            //訂閱事件(類似于 方法與委托事件的關聯)
            event1.NotifyEveryOne += new DelegatEventTest.MyDelegateEventHandler(objA.DispInfo);
            //event1.NotifyEveryOne += new DelegatEventTest.MyDelegateEventHandler(objB.DispInfo);
 
            event1.Notify();
 
            richTextBox1.AppendText(objA.ClassAinfo + "\r");
            richTextBox1.AppendText(objB.ClassAinfo + "\r");
        }

帶參數的事件案例

參考網上的案例,場景:首領boyK要搞一場鴻門宴,吩咐部下boyA和boyB各自帶隊埋伏在屏風兩側,約定以杯為令:若左手舉杯,則boyA帶隊殺出;若右手舉杯,則boyB帶隊殺出;若直接摔杯,則boyA和boyB同時殺出。boyA和boyB襲擊的具體方法,首領boyK并不關心。

boyK的定義

        public class BoyK
        {
            //定義委托
            public delegate void RaiseEventHandler(string hand);
            public delegate void FallEventHandler();
 
            //定義事件
            public event RaiseEventHandler RaiseEvent;
            public event FallEventHandler FallEvent;
 
            //調用事件(例:舉手事件)
            public void Raise(string hand)
            {
                if (RaiseEvent!=null)
                {
                    RaiseEvent(hand);
                }
            }
            //調用事件(例:摔杯事件)
            public void Fall()
            {
                if (FallEvent!=null)
                {
                    FallEvent();
                }
            }            
        }

boyA的定義

        class BoyA
        {
            public string str = "A待命";
            BoyK boyk;
            public BoyA(BoyK k)
            {
                boyk = k;
                k.RaiseEvent += new BoyK.RaiseEventHandler(k_RaiseEvent);   //訂閱舉杯事件
                k.FallEvent += new BoyK.FallEventHandler(k_FallEvent);      //訂閱摔杯事件
            }
            public void Attack()
            {
                str = "A開始**";
            }
 
            //boyK舉杯的動作
            void k_RaiseEvent(string hand)
            {
                if (hand.Equals("左"))
                {
                    Attack();
                }
            }
 
            void k_FallEvent()
            {
                Attack();
            }         
        }

boyB的定義

        class BoyB
        {
            public string str = "B待命";
            BoyK boyk;
            public BoyB(BoyK k)
            {
                boyk = k;
                k.RaiseEvent += new BoyK.RaiseEventHandler(k_RaiseEvent);   //訂閱舉杯事件
                k.FallEvent += new BoyK.FallEventHandler(k_FallEvent);      //訂閱摔杯事件
            }
 
            public void Attack()
            {
                str = "B開始**";
            }
 
            void k_RaiseEvent(string hand)
            {
                if (hand.Equals("右"))
                {
                    Attack();
                }
            }
 
            void k_FallEvent()
            {
                Attack();
            }
        }

事件的使用

        private void button2_Click(object sender, EventArgs e)
        {
            BoyK boyK = new BoyK();
            BoyA boyA = new BoyA(boyK);
            BoyB boyB = new BoyB(boyK);
 
            //boyK.Raise("左");
            boyK.Raise("右");
            //boyK.Fall();
 
            richTextBox1.AppendText(boyA.str+"\r");
            richTextBox1.AppendText(boyB.str + "\r");
        }

運行效果

回調函數的使用案例

實際開發中,下面這個類會封裝起來,只提供函數接口。相當于系統底層

        //實際開發中,下面這個類會封裝起來,只提供函數接口。相當于系統底層
        class CalculateClass
        {
            public delegate int SomeCalculateWay(int num1, int num2);
            //將傳入參數在系統底層進行某種處理,具體計算方法由開發者開發,函數僅提供執行計算方法后的返回值
            //下面的代碼中相當于調用了一個回調函數
            public int Calculate(int num1, int num2, SomeCalculateWay call)
            {
                return call(num1, num2);
            }
        }

開發層處理,開發人員編寫具體的計算方法

        //開發層處理,開發人員編寫具體的計算方法
        class FunctionClass
        {
            public int GetSum(int a, int b)
            {
                return a + b;
            }
 
            public int GetMulti(int a, int b)
            {
                return a * b;
            }
        }

用戶層,執行輸入等操作

        private void button4_Click(object sender, EventArgs e)
        {
            CalculateClass cc = new CalculateClass();
            FunctionClass fc = new FunctionClass();
 
            int result1 = cc.Calculate(2, 3, fc.GetSum);
            int result2 = cc.Calculate(2, 3, fc.GetMulti);
 
            richTextBox1.AppendText(result1 + "\r");
            richTextBox1.AppendText(result2 + "\r");
        }

說明:上述代碼中的FunctionClass中的GetSum()和GetMulti()兩個函數稱為回調函數。

可以看到整個程序中并沒有哪個地方通過類似GetSum(1,2)這種形式調用了該函數,只有將其當作另一個函數的參數來進行調用。

如cc.PrintAndCalculate(2, 3, fc.GetSum)。

原文鏈接:https://blog.csdn.net/zhigedali/article/details/122928563

欄目分類
最近更新