網站首頁 編程語言 正文
委托是一個類,它定義了方法的類型,使得可以將方法當作另一個方法的參數來進行傳遞,這種將方法動態地賦給參數的做法,可以避免在程序中大量使用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
相關推薦
- 2022-05-03 EF使用Code?First模式生成單數形式表名_實用技巧
- 2022-07-09 docker 中進程的信號
- 2024-01-10 CloneNotSupportedException的解決方案 + Object的clone方法分析
- 2022-08-05 RedisConfig 配置文件
- 2022-10-31 Golang中map數據類型的使用方法_Golang
- 2022-09-01 openGauss數據庫在CentOS上的安裝實踐記錄_數據庫其它
- 2022-09-30 Go語言編譯原理之源碼調試_Golang
- 2022-09-05 RocketMQ 4.9.4使用(五)關閉info日志打印
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支