C#中委托、事件和回調(diào)的使用及說明
委托是一個類,它定義了方法的類型,使得可以將方法當(dāng)作另一個方法的參數(shù)來進行傳遞,這種將方法動態(tài)地賦給參數(shù)的做法,可以避免在程序中大量使用If-Else(Switch)語句,同時使得程序具有更好的可擴展性。
事件是對委托的封裝。如果不進行封裝,讓委托暴露給調(diào)用者,調(diào)用者就可以把委托變量重新引用到新的委托對象,也就刪除了當(dāng)前要調(diào)用的方法列表;
定義一個事件有兩步,首先定義一個委托,它包括了這件事的“協(xié)議”和委托方法(由誰去做);其次,用event關(guān)鍵字和相關(guān)委托聲明這個事件。事件像是一個接口,封裝了委托所定的“協(xié)議”。由于委托已經(jīng)定義了協(xié)議,剩下的就是按這個協(xié)議去辦事,至于怎么做它并不關(guān)心。調(diào)用者無法訪問委托對象。
回調(diào)函數(shù)就是把一個方法的傳給另外一個方法去執(zhí)行。回調(diào)函數(shù)只是一個功能片段,由用戶按照回調(diào)函數(shù)的調(diào)用約定來實現(xiàn)的一個函數(shù)??梢园讶我庖粋€符合這個委托的方法傳遞進去,意思就是說這部分代碼是可變的。而設(shè)計上有一個抽離出可變部分代碼的原則,這種用法無疑可以用到那種場合了。從上可知,事件和回調(diào)都是對委托的一種用法。事件是把委托封裝起來,而回調(diào)函數(shù)則是由委托綁定不同的函數(shù)來實現(xiàn)不同的功能。
委托的使用案例
定義委托和方法
//委托定義(要與方法中參數(shù)一致)
public delegate int DelegateTest(int n1, int n2);
class Math
{
//方法定義(委托要執(zhí)行的方法,本案例把方案寫到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();
//創(chuàng)建委托對象
DelegateTest delegateDemo1;
//將方法與委托對象關(guān)聯(lián)起來 (委托:將方法當(dāng)作另一個方法的參數(shù)來進行傳遞)
//delegateDemo1 = new CallDelegate(objMath.Multiply);
delegateDemo1 = objMath.Multiply; //與上面方法相同
//delegateDemo1 += objMath.AddTest; //給委托對象再綁定一個方法,若該條代碼執(zhí)行,顯示結(jié)果為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");
}執(zhí)行的結(jié)果

利用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 默認(rèn)!";
public void DispInfo()
{
ClassAinfo = "A 收到!";
}
}
class ClassB
{
public string ClassAinfo = "B 默認(rèn)!";
public void DispInfo()
{
ClassAinfo = "B 收到!";
}
}
class DelegatEventTest
{
//定義委托
public delegate void MyDelegateEventHandler();
//定義事件
public event MyDelegateEventHandler NotifyEveryOne;
//調(diào)用事件
public void Notify()
{
if (NotifyEveryOne != null)
{
NotifyEveryOne();
}
}
}事件的使用
private void button3_Click(object sender, EventArgs e)
{
//創(chuàng)建classA和classB的對象
ClassA objA = new ClassA();
ClassB objB = new ClassB();
//創(chuàng)建委托的對象
DelegatEventTest event1 = new DelegatEventTest();
//訂閱事件(類似于 方法與委托事件的關(guān)聯(lián))
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");
}
帶參數(shù)的事件案例
參考網(wǎng)上的案例,場景:首領(lǐng)boyK要搞一場鴻門宴,吩咐部下boyA和boyB各自帶隊埋伏在屏風(fēng)兩側(cè),約定以杯為令:若左手舉杯,則boyA帶隊殺出;若右手舉杯,則boyB帶隊殺出;若直接摔杯,則boyA和boyB同時殺出。boyA和boyB襲擊的具體方法,首領(lǐng)boyK并不關(guān)心。
boyK的定義
public class BoyK
{
//定義委托
public delegate void RaiseEventHandler(string hand);
public delegate void FallEventHandler();
//定義事件
public event RaiseEventHandler RaiseEvent;
public event FallEventHandler FallEvent;
//調(diào)用事件(例:舉手事件)
public void Raise(string hand)
{
if (RaiseEvent!=null)
{
RaiseEvent(hand);
}
}
//調(diào)用事件(例:摔杯事件)
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");
}運行效果

回調(diào)函數(shù)的使用案例
實際開發(fā)中,下面這個類會封裝起來,只提供函數(shù)接口。相當(dāng)于系統(tǒng)底層
//實際開發(fā)中,下面這個類會封裝起來,只提供函數(shù)接口。相當(dāng)于系統(tǒng)底層
class CalculateClass
{
public delegate int SomeCalculateWay(int num1, int num2);
//將傳入?yún)?shù)在系統(tǒng)底層進行某種處理,具體計算方法由開發(fā)者開發(fā),函數(shù)僅提供執(zhí)行計算方法后的返回值
//下面的代碼中相當(dāng)于調(diào)用了一個回調(diào)函數(shù)
public int Calculate(int num1, int num2, SomeCalculateWay call)
{
return call(num1, num2);
}
}開發(fā)層處理,開發(fā)人員編寫具體的計算方法
//開發(fā)層處理,開發(fā)人員編寫具體的計算方法
class FunctionClass
{
public int GetSum(int a, int b)
{
return a + b;
}
public int GetMulti(int a, int b)
{
return a * b;
}
}用戶層,執(zhí)行輸入等操作
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()兩個函數(shù)稱為回調(diào)函數(shù)。
可以看到整個程序中并沒有哪個地方通過類似GetSum(1,2)這種形式調(diào)用了該函數(shù),只有將其當(dāng)作另一個函數(shù)的參數(shù)來進行調(diào)用。
如cc.PrintAndCalculate(2, 3, fc.GetSum)。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#模擬實現(xiàn)鼠標(biāo)自動點擊與消息發(fā)送功能
這篇文章主要為大家詳細(xì)介紹了C#如何利用windows api來模擬實現(xiàn)鼠標(biāo)點擊、右擊、雙擊以及發(fā)送文本功能,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08
C#中IsNullOrEmpty和IsNullOrWhiteSpace的使用方法及區(qū)別解析
今天我們將探討C#中兩個常用的字符串處理方法:IsNullOrEmpty和IsNullOrWhiteSpace,本文中,我們將詳細(xì)解釋這兩個方法的功能和使用場景,并幫助您更好地理解它們之間的區(qū)別,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-07-07

