C#關(guān)于Func和Action委托的介紹詳解
委托:委托(Delegate) 是存有對(duì)某個(gè)方法的引用的一種引用類(lèi)型變量。引用可在運(yùn)行時(shí)被改變。
委托(Delegate)特別用于實(shí)現(xiàn)事件和回調(diào)方法。所有的委托(Delegate)都派生自 System.Delegate 類(lèi)。
1.Action委托
沒(méi)有返回值,可以不包含參數(shù)
(1)聲明委托、定位委托事件、向委托添加事件、執(zhí)行委托
/// <summary> /// 不包含參數(shù) /// </summary> private event Action Action_0; /// <summary> /// 包含一個(gè)參數(shù) /// </summary> private event Action<int> Action_1; /// <summary> /// 包含兩個(gè)參數(shù) /// </summary> private event Action<int, double> Action_2; /// <summary> /// 包含三個(gè)參數(shù) /// </summary> private event Action<int, double, string> Action_3; /// <summary> /// 定義沒(méi)有參數(shù)委托的事件 /// </summary> private void Fun_0() { Console.WriteLine("沒(méi)有參數(shù)"); } /// <summary> /// 定義包含一個(gè)參數(shù)委托的事件 /// </summary> private void Fun_1(int nInt) { Console.WriteLine($"包含一個(gè)參數(shù):{nInt}"); } /// <summary> /// 定義包含兩個(gè)參數(shù)委托的事件 /// </summary> private void Fun_2(int nInt, double dDouble) { Console.WriteLine($"包含兩個(gè)參數(shù),參數(shù)值:{nInt},{dDouble}"); } /// <summary> /// 定義包含三個(gè)參數(shù)委托的事件 /// </summary> private void Fun_3(int nInt, double dDouble, string str) { Console.WriteLine($"包含三個(gè)參數(shù),參數(shù)值:{nInt},{dDouble},{str}"); } //點(diǎn)擊事件 private void btn_Click(object sender, EventArgs e) { //向委托添加事件 Action_0 += Fun_0; Action_1 += Fun_1; Action_2 += Fun_2; Action_3 += Fun_3; //執(zhí)行委托 Action_0.Invoke(); Action_1.Invoke(666); Action_2.Invoke(666,888.0); Action_3.Invoke(666,888,"Hello World"); }
輸出結(jié)果:
由于btn_Click為點(diǎn)擊事件,點(diǎn)擊第二次(第二次點(diǎn)擊會(huì)再次向委托添加事件)的數(shù)據(jù)結(jié)果如下:
因此,向委托添加事件時(shí),一個(gè)事件僅添加一次即可,若進(jìn)行多次添加則調(diào)用委托時(shí)會(huì)將添加進(jìn)入委托的所有事件進(jìn)行調(diào)用,無(wú)論該事件是否已添加都會(huì)進(jìn)行調(diào)用,故做如下處理(在構(gòu)造函數(shù)中或在程序啟動(dòng)時(shí)添加委托事件):
上圖中委托調(diào)用時(shí)提示波浪線(xiàn),因?yàn)槭俏性谡{(diào)用時(shí)可能未添加事件,將會(huì)拋出:未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例的異常信息,
異常信息:
故調(diào)用時(shí)進(jìn)行異常處理或做如下處理:
處理方案1:
private void button1_Click(object sender, EventArgs e) { Action_0?.Invoke(); Action_1?.Invoke(666); Action_2?.Invoke(666, 888.0); Action_3?.Invoke(666, 888, "Hello World"); }
處理方案2
//執(zhí)行委托 private void button1_Click(object sender, EventArgs e) { try { Action_0.Invoke(); Action_1.Invoke(666); Action_2.Invoke(666, 888.0); Action_3.Invoke(666, 888, "Hello World"); } catch (Exception ex) { MessageBox.Show("調(diào)用出現(xiàn)異常", "提示"); } }
此時(shí),我們已經(jīng)學(xué)會(huì)了Action委托的簡(jiǎn)單使用,這時(shí)會(huì)有人考慮到,我想調(diào)用完返回信息Action委托并沒(méi)有返回,會(huì)限制我們的使用,不要著急,我們系統(tǒng)已經(jīng)幫我們準(zhǔn)備了一個(gè)現(xiàn)成的委托類(lèi)型Func,下面我們對(duì)Func做個(gè)介紹。
2.Func委托
話(huà)不多說(shuō),上代碼,以下我們定義了包含兩個(gè)參數(shù)int和double,返回值為string類(lèi)型的Func委托,并添加了兩個(gè)事件Fun_1和Fun_2:
public partial class Form1 : Form { /// <summary> /// 包含兩個(gè)參數(shù)int和double,返回值為string類(lèi)型委托 /// </summary> private event Func<int, double, string> TestFunc; /// <summary> /// 定義委托的事件 /// </summary> private string Fun_1(int nInt, double dDouble) { Console.WriteLine($"參數(shù)值:{nInt},{dDouble}"); return "事件:Fun_1"; } /// <summary> /// 定義委托的事件 /// </summary> private string Fun_2(int nInt, double dDouble) { Console.WriteLine($"參數(shù)值:{nInt},{dDouble}"); return "事件:Fun_2"; } /// <summary> /// 窗體構(gòu)造函數(shù) /// </summary> public Form1() { InitializeComponent(); InitAction(); } //向委托添加事件 private void InitAction() { TestFunc += Fun_1; TestFunc += Fun_2; } //執(zhí)行委托 private void button1_Click(object sender, EventArgs e) { var result = TestFunc?.Invoke(888, 10); Console.WriteLine($"返回結(jié)果:{result}"); } }
輸出結(jié)果:
從輸出結(jié)果不難看出向委托添加多個(gè)事件(委托的多播或組播),委托包含返回值時(shí),僅得到最后向委托添加的事件(方法)的返回值,所以在使用有返回值時(shí)必須注意這一點(diǎn)。
以下為先添加Fun_2后添加Fun_1的返回結(jié)果:
到這里,委托的介紹我們已經(jīng)介紹完了,更多相關(guān)C# Func 和Action 委托內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# 7.2中結(jié)構(gòu)體性能問(wèn)題的解決方案
這篇文章主要給大家介紹了關(guān)于C# 7.2中結(jié)構(gòu)體性能問(wèn)題的解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08C#正則過(guò)濾HTML標(biāo)簽并保留指定標(biāo)簽的方法
這篇文章主要介紹了C#正則過(guò)濾HTML標(biāo)簽并保留指定標(biāo)簽的方法,涉及C#針對(duì)頁(yè)面HTML元素正則匹配與替換相關(guān)操作技巧,需要的朋友可以參考下2017-06-06c#中winform根據(jù)郵箱地址和密碼一鍵發(fā)送email的實(shí)現(xiàn)
本文主要介紹了c#winform根據(jù)郵箱地址和密碼一鍵發(fā)送email的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07解決用Aspose.Words,在word文檔中創(chuàng)建表格的實(shí)現(xiàn)方法
本篇文章是對(duì)利用Aspose.Words,在word文檔中創(chuàng)建表格的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05利用WPF實(shí)現(xiàn)Windows屏保的制作
屏保程序的本質(zhì)上就是一個(gè)Win32?窗口應(yīng)用程序。本文將利用WPF實(shí)現(xiàn)Windows屏保的制作,文中的示例代碼簡(jiǎn)潔易懂,對(duì)我們學(xué)習(xí)WPF有一定幫助,感興趣的可以了解一下2022-07-07C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法
這篇文章主要介紹了C#實(shí)現(xiàn)appSettings節(jié)點(diǎn)讀取與修改的方法,是非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10webBrowser執(zhí)行js的方法,并返回值,c#后臺(tái)取值的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇webBrowser執(zhí)行js的方法,并返回值,c#后臺(tái)取值的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12