使用.NET中的Action及Func泛型委托深入剖析
委托,在C#編程中占有極其重要的地位,委托可以將函數(shù)封裝到委托對(duì)象中,并且多個(gè)委托可以合并為一個(gè)委托,委托對(duì)象則可以像普通對(duì)象一樣被存儲(chǔ)、傳遞,之后在任何時(shí)刻進(jìn)行調(diào)用,因此,C#中函數(shù)回調(diào)機(jī)制的實(shí)現(xiàn)基本上依賴于委托。C#的delegate關(guān)鍵字用于聲明委托,它具有將聲明委托類型映射到System.Delegate類的能力,System.Delegate類位于mscorlib.dll中,是.NET的基礎(chǔ)核心類之一。使用delegate關(guān)鍵字聲明一個(gè)委托,實(shí)質(zhì)上創(chuàng)建了System.Delegate的派生類,因此委托類型并非結(jié)構(gòu)體也不是其它類型,它是一個(gè)類。一個(gè)委托對(duì)象也就是一個(gè)類的實(shí)例。以下是Delegate類的聲明:
public abstract class Delegate
Delegate是所以委托類型的基類,C#中的多播委托實(shí)際上是MulticastDelegate類,它是System.Delegate的派生類,而本文中介紹的Action、Func泛型委托實(shí)際上都是MulticastDelegate類的派生類型。C#中當(dāng)我們使用delegate關(guān)鍵字聲明一個(gè)委托類型時(shí),實(shí)際上是由C#編譯器根據(jù)我們聲明時(shí)的方法簽名幫助我們生成一個(gè)與簽名匹配的,派生自MulticastDelegate的類。在泛型大量應(yīng)用之前,我們寫一個(gè)C#程序的時(shí)候可能會(huì)使用delegate關(guān)鍵字聲明許多委托類型,因?yàn)檫@些類型都對(duì)應(yīng)于不同的方法簽名。通過(guò)Visual Studio的對(duì)象瀏覽器查看mscorlib可以看到這兩種重要的泛型委托:
其中除了Action之外,其它的委托都是泛型的,其實(shí)就是一些泛型類。這便是.NET核心庫(kù)中全部的泛型委托了。這些泛型委托分為Func、Action中,它們借助于泛型特性,可以替代C#中幾乎所有的委托類型,也就是說(shuō)一般情況下,在我們的程序中不必再聲明任何新的委托類型,就可以包裝所有的函數(shù)了。比如我們有兩個(gè)方法:
public static void OtputString(string str)
{
Console.WriteLine(str);
}
public static int Add(int a, int b)
{
return a + b;
}
Func泛型委托與Action相比即多出了一個(gè)TResult類型參數(shù),用于函數(shù)具有返回值的情況,Action泛型委托用于沒(méi)有返回值的函數(shù)。當(dāng)我們要獲得這兩個(gè)方法的委托對(duì)象時(shí)這樣變可以了:
var action = new Action<string>(OtputString);
action("OutputString Invoked!");
var func = new Func<int, int, int>(Add);
var sum = func(3, 5);
Console.WriteLine(sum);
可以看見(jiàn),當(dāng)我們將具有返回值的函數(shù)包裝成委托對(duì)象時(shí)使用Func委托,如果函數(shù)沒(méi)有返回值則使用Action,核心庫(kù)提供的泛型委托類型參數(shù)最短的為0,最長(zhǎng)的為8個(gè)。因此,Action及其泛型委托可以匹配無(wú)返回值、參數(shù)數(shù)量為0到8的任何函數(shù)。同樣的,F(xiàn)unc泛型委托可以匹配由返回值、參數(shù)數(shù)量在0到8個(gè)的任何函數(shù)。一般情況下,程序中函數(shù)的參數(shù)數(shù)量都不會(huì)超過(guò)8個(gè),即使超過(guò)8個(gè),我們可以聲明新的泛型委托類型來(lái)應(yīng)對(duì)
delegate void Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9);
使用這些泛型委托不會(huì)有任何的性能損失,使得程序中委托的使用風(fēng)格保持一致。唯一的缺點(diǎn)就是類型的名稱無(wú)法表達(dá)具體的用途,舉例來(lái)講EventHandler委托,我們一看名字就知道這是用于事件處理的委托。而使用Action<object,EventArgs>委托我們則無(wú)法從名稱看出這種類型的委托是何種用途。
泛型委托有替代所有其它委托的能力,到底應(yīng)該使用泛型委托還是普通委托、何時(shí)使用、在哪種情況下用,可能每個(gè)人都有不同的簡(jiǎn)介,不過(guò)說(shuō)到底,泛型委托能統(tǒng)一程序代碼風(fēng)格以及隨處方便使用等優(yōu)點(diǎn)是非常顯著的。
相關(guān)文章
ASP.NET中操作數(shù)據(jù)庫(kù)的基本步驟分享
ASP.NET中操作數(shù)據(jù)庫(kù)的基本步驟分享,學(xué)習(xí)asp.net的朋友可以參考下。2011-10-10
Asp.net+jquery+.ashx文件實(shí)現(xiàn)分頁(yè)思路
分頁(yè)思路: .ashx程序中,編寫好取得不同頁(yè)碼的程序。在頁(yè)面布局好的前提下,留下數(shù)據(jù)區(qū)域 div。然后在頁(yè)面請(qǐng)求 .ashx程序生成下一頁(yè)的html代碼。覆蓋div.innerHTMl2013-03-03
ASP.NET?Core中使用Redis實(shí)現(xiàn)緩存
本文詳細(xì)講解了ASP.NET?Core中使用Redis實(shí)現(xiàn)緩存的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
log4net創(chuàng)建系統(tǒng)日志的詳細(xì)步驟
log4net是.Net下一個(gè)非常優(yōu)秀的開源日志記錄組件。log4net記錄日志的功能非常強(qiáng)大。它可以將日志分不同的等級(jí),以不同的格式,輸出到不同的媒介。本文主要是簡(jiǎn)單的介紹如何在Visual Studio2010(Asp.Net Mvc3.0)中使用log4net快速創(chuàng)建系統(tǒng)日志,如何擴(kuò)展以輸出自定義字段2013-11-11
ASP.NET 圖片加水印防盜鏈實(shí)現(xiàn)代碼
ASP.NET 圖片加水印防盜鏈實(shí)現(xiàn)代碼,需要的朋友可以參考下。2011-12-12
asp.net 結(jié)合mysql存儲(chǔ)過(guò)程進(jìn)行分頁(yè)代碼
最近用mysql + asp.net來(lái)寫網(wǎng)站,既然mysql已經(jīng)支持存儲(chǔ)過(guò)程了,那么像分頁(yè)這么常用的東西,當(dāng)然要用存儲(chǔ)過(guò)程啦2008-11-11
Asp.net中將Word文件轉(zhuǎn)換成HTML的方法
這篇文章主要介紹了Asp.net中將Word文件轉(zhuǎn)換成HTML的方法,需要的朋友可以參考下2014-08-08
淺談ASP.NETCore統(tǒng)一處理404錯(cuò)誤都有哪些方式
本文主要介紹了ASP.NETCore統(tǒng)一處理404錯(cuò)誤都有哪些方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
asp.net(C#) 動(dòng)態(tài)添加非ASP的標(biāo)準(zhǔn)html控件(如添加Script標(biāo)簽)
在開發(fā)程序時(shí),有時(shí)需要?jiǎng)討B(tài)添加標(biāo)簽,而有部分又不是ASP控件,偶然找到這段代碼,特收藏。2009-07-07



