c# 委托的常見(jiàn)用法
此篇文章是我一個(gè)小白對(duì)委托的理解和總結(jié),請(qǐng)高手多多評(píng)判指教。
委托就是一種后期綁定機(jī)制,說(shuō)的直白點(diǎn)就是在調(diào)用的時(shí)候才去傳遞業(yè)務(wù)邏輯的一種算法。
委托的創(chuàng)建語(yǔ)法:
public delegate int Comparison<in T>(T left, T right);//官方給出的定義泛型委托的demo
語(yǔ)法看似像聲明一個(gè)變量或方法的簽名,但實(shí)現(xiàn)上是在聲明一個(gè)類(lèi)型。編譯器會(huì)生成一個(gè)派生自System.MulticastDelegate的類(lèi)(而System.MulticastDelegate派生自System.Delegate),類(lèi)型名與委托的名字相同,其中包含Invoke 、BeginInvoke和EndInvoke等方法。編譯器還為這個(gè)新類(lèi)型生成添加和刪除處理業(yè)務(wù),以便該類(lèi)的客戶(hù)端可以在實(shí)例的調(diào)用列表中添加和刪除方法。
委托可以被定義在類(lèi)的內(nèi)部、名稱(chēng)空間下(與類(lèi)同級(jí))和全局名稱(chēng)空間下(不推薦)。
//在全局定義
public delegate int Comparison<in T>(T left, T right);
namespace Test
{
//在指定名稱(chēng)空間下定義
public delegate int Comparison2<in T>(T left, T right);
public class Student
{
//在類(lèi)內(nèi)部定義
public delegate int Comparison3<in T>(T left, T right);
}
}
委托的定義賦值
將委托當(dāng)成類(lèi)使用(委托本身就是一個(gè)類(lèi))。
//定義委托
public delegate int Comparison<in T>(T left, T right);
public class Test
{
//定義
private Comparison<int> comparator;
public void Show()
{
//賦值 請(qǐng)注意,使用的是方法名稱(chēng),不帶括號(hào),將方法附加給委托作為委托的調(diào)用方法。
this.comparator = Compare;
//調(diào)用
this.comparator(1, 2); //調(diào)用方式二 this.comparator.Invoke(1, 2);
}
private int Compare(int left, int right) => left.CompareTo(right);
}
當(dāng)用作委托的目標(biāo)方法是“小方法”的情況下,通常使用lambda表達(dá)式語(yǔ)法來(lái)執(zhí)行賦值:
Comparison<string> comparer = (left, right) => left.Length.CompareTo(right.Length);
多播委托
通常只是將單個(gè)目標(biāo)方法附加到委托。但是,委托對(duì)象確實(shí)支持將多個(gè)目標(biāo)方法附加到一個(gè)委托對(duì)象的調(diào)用列表,稱(chēng)為多播委托。多播委托意味著通過(guò)委托調(diào)用時(shí)可以調(diào)用多個(gè)方法,所以可以為委托附加多個(gè)方法。
private int Cal(int num) {return num * num;}
private void button1_Click(object sender, EventArgs e)
{
Func<int, int> action = null;
//使用+= 或 -= 來(lái)增加或移除委托實(shí)例
action += a => { Console.WriteLine($"第{1}次執(zhí)行" + a); return a + 1; };
action += Cal;
action += a => { Console.WriteLine($"第{3}次執(zhí)行" + a); return a + 3; };
action -= Cal;
//如果有返回值的話,返回的是最后一次執(zhí)行的結(jié)果
int a = action(5);
Console.WriteLine(a);
}
常用泛型委托
無(wú)返回值
public delegate void Action(); public delegate void Action<in T>(T arg); public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2); // Other variations removed for brevity.
有返回值
public delegate TResult Func<out TResult>(); public delegate TResult Func<in T1, out TResult>(T1 arg); public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2); // Other variations removed for brevity
返回bool類(lèi)型
public delegate bool Predicate<in T>(T obj);
注意:在.net core平臺(tái)中,不支持委托目標(biāo)方法的異步調(diào)用(即不支持BeginInvoke方法):
Action action = () => Console.WriteLine("委托執(zhí)行了");
AsyncCallback asyncCallback = a => Console.WriteLine("回調(diào)執(zhí)行了" + a);
//System.PlatformNotSupportedException:“Operation is not supported on this platform.”
IAsyncResult result = action.BeginInvoke(asyncCallback, "asdf"); //委托啟動(dòng)異步調(diào)用
action.EndInvoke(result);
Event 事件
事件是帶event關(guān)鍵字的委托的實(shí)例,event可以限制被外部調(diào)用(invoke)和直接賦值(=)。委托是一個(gè)類(lèi)型,而事件是委托類(lèi)型的一個(gè)實(shí)例。
聲明一個(gè)事件很簡(jiǎn)單,只需在聲明一個(gè)委托對(duì)象時(shí)加上event關(guān)鍵字就行。
/// <summary>
/// 定義一個(gè)委托
/// </summary>
/// <param name="name"></param>
public delegate void ShowInfo(string name);
public class Study
{
/// <summary>
/// 聲明一個(gè)事件
/// </summary>
public event ShowInfo ShowInfo;
public void Show()
{
ShowInfo += Study_ShowInfo;
//只能在“publisher”類(lèi)中調(diào)用
ShowInfo("asdf");
}
private void Study_ShowInfo(string name)
{
throw new NotImplementedException();
}
}
可以在用事件的地方用委托來(lái)替代,但事件有一系列規(guī)則和約束用以保證程序的安全可控,事件只有 += 和 -= 操作,這樣訂閱者只能有訂閱或取消訂閱操作,沒(méi)有權(quán)限執(zhí)行其它操作。如果是委托,那么訂閱者就可以使用 = 來(lái)對(duì)委托對(duì)象重新賦值(其它訂閱者全部被取消訂閱),甚至將其設(shè)置為null,甚至訂閱者還可以直接調(diào)用委托,這些都是很危險(xiǎn)的操作,廣播者就失去了獨(dú)享控制權(quán)。
事件保證了程序的安全性和健壯性。
以上就是c# 委托的常見(jiàn)用法的詳細(xì)內(nèi)容,更多關(guān)于c# 委托的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入U(xiǎn)nix時(shí)間戳與C# DateTime時(shí)間類(lèi)型互換的詳解
本篇文章是對(duì)Unix時(shí)間戳與C# DateTime時(shí)間類(lèi)型互換進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
在C#中對(duì)TCP客戶(hù)端的狀態(tài)封裝詳解
本篇文章小編為大家介紹,在C#中對(duì)TCP客戶(hù)端的狀態(tài)封裝詳解,需要的朋友參考下2013-04-04
C# 判斷字符為空的6種方法的效率實(shí)測(cè)對(duì)比
本文主要介紹了C#中判斷字符是否為空的方法,并實(shí)測(cè)對(duì)比各種方法的執(zhí)行效率,最后推薦大家使用IsNullOrEmpty,效率和易用性比較均衡。2016-05-05
可替代log4j日志的c#簡(jiǎn)單日志類(lèi)隊(duì)列實(shí)現(xiàn)類(lèi)代碼分享
C#生成圖形驗(yàn)證碼的實(shí)現(xiàn)方式
C#實(shí)現(xiàn)熱更新服務(wù)器程序的具體過(guò)程

