最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C#中delegate/event/EventHandler/Action/Func的使用和區(qū)別

 更新時(shí)間:2023年04月03日 09:55:48   作者:高級(jí)夢(mèng)想家  
這篇文章主要為大家詳細(xì)介紹了C#中delegate、event、EventHandler、Action和Func的使用與區(qū)別,文中的示例代碼講解詳細(xì),感興趣的可以了解一下

1 委托

在.NET中定義“委托”需要用到delegate關(guān)鍵字,它是存有對(duì)某個(gè)方法的引用的一種引用類型變量,類似于 C 或 C++ 中函數(shù)的指針。“委托”主要有兩大作用:

(1)將方法當(dāng)作參數(shù)傳遞

(2)方法的一種多態(tài)(類似于一個(gè)方法模板,可以匹配很多個(gè)方法)

下面,給出一個(gè)展現(xiàn)了上述兩大作用的委托代碼示例:

//定義一個(gè)委托
        public delegate int MyDelegate(int x, int y);

        //與委托匹配的一個(gè)方法
        public static int Add(int a, int b)
        {
            return a + b;
        }

        //與委托匹配的另一個(gè)方法
        public static int Reduce(int a, int b)
        {
            return a - b;
        }

        //示例:將委托/方法當(dāng)參數(shù)傳遞
        public static int Test(MyDelegate MD)
        {
            return MD(10, 20);
        }

        static void Main(string[] args)
        {
            int a, b, x, y;

            MyDelegate md;

            //將委托指向Add這個(gè)方法,并進(jìn)行相關(guān)操作
            md = Add;
            a = md(1, 2);
            b = Test(md);

            //再將委托指向Reduce這個(gè)方法,并進(jìn)行相關(guān)操作
            md = Reduce;
            x = md(7, 2);
            y = Test(md);

            Console.WriteLine($"1+2={a},10+20=,7-2={x},10-20={y}");
            Console.ReadLine();
        }

執(zhí)行以上程序,輸出結(jié)果如下:

1+2=3,10+20=30,7-2=5,10-20=-10

委托也可以使用+=/-=來實(shí)現(xiàn)“發(fā)布/訂閱”模式,示例代碼如下:

//定義一個(gè)委托
        public delegate void MyDelegate1(int x);

        public static void Method1(int a)
        {
            Console.WriteLine($"a={a}");
        }

        public static void Method2(int b)
        {
            Console.WriteLine($"b=");
        }

        static void Main(string[] args)
        {
            MyDelegate1 md = null;
            md += Method1;
            md += Method2;
            md(35);

            Console.ReadLine();
        }

以上程序輸出如下:

a=35
b=35

但是委托有一個(gè)弊端,它可以使用“=”將所有已經(jīng)訂閱的取消,只保留=后的這一個(gè)訂閱。

為了解決這個(gè)弊端,事件event應(yīng)運(yùn)而生。

2 事件-概念的引出

事件event是一種特殊的委托,它只能+=,-=,不能直接用=。

event在定義類中(發(fā)布者)是可以直接=的,但是在其他類中(訂閱者)就只能+= -=了,也就是說發(fā)布者發(fā)布一個(gè)事件后,訂閱者針對(duì)他只能進(jìn)行自身的訂閱和取消。

下面是定義一個(gè)事件的代碼:

//定義一個(gè)委托
        public delegate void MyDelegate1(int x);
        //定義一個(gè)事件
        public event MyDelegate1 emd;

經(jīng)過長(zhǎng)久的經(jīng)驗(yàn)積累后,人們發(fā)現(xiàn),絕大多數(shù)事件的定義,是用public delegate void XXX(object sender, EventArgs e);這樣一個(gè)委托原型進(jìn)行定義的,是一件重復(fù)性的工作,于是,EventHandler應(yīng)運(yùn)而生。它的出現(xiàn)就是為了避免這種重復(fù)性工作,并建議盡量使用該類型作為事件的原型。

//@sender: 引發(fā)事件的對(duì)象
//@e: 傳遞的參數(shù)
public delegate void EventHandler(object sender, EventArgs e);

//使用
public event EventHandler emd;

下面給出一個(gè)使用事件的具體示例:

public class Demo
        {
            public event EventHandler emd;
            public void RaiseEvent()
            {
                emd(this, EventArgs.Empty);
            }
        }

        static void Main(string[] args)
        {
            var instance = new Demo();
            instance.emd += (sender, arg) =>
            {
                Console.WriteLine("執(zhí)行事件1!");
            };

            instance.emd += (sender, arg) =>
            {
                Console.WriteLine("執(zhí)行事件2!");
            };

            instance.RaiseEvent();

            Console.ReadLine();
        }

這里我們先定義一個(gè)Demo類,其內(nèi)部有個(gè)事件是emd,我們給他開放了一個(gè)接口RaiseEvent,如果誰敢調(diào)用它,那么,它就觸發(fā)報(bào)警事件emd。

這里模擬了2個(gè)訂閱者,分別處理報(bào)警事件emd。

程序執(zhí)行結(jié)果如下:

執(zhí)行事件1!
執(zhí)行事件2!

同時(shí),我們也可以看出:事件是按照+=的訂閱先后順序執(zhí)行的。

3 事件-關(guān)于異常

現(xiàn)在,我們?cè)诘谝粋€(gè)訂閱者中加入異常,如下:

instance.emd += (sender, arg) =>
    {
        Console.WriteLine("執(zhí)行事件1!");
        throw new Exception("執(zhí)行事件1,錯(cuò)誤");
    };

執(zhí)行后發(fā)現(xiàn),第1個(gè)訂閱者事件觸發(fā)拋出異常后,第2個(gè)訂閱者的事件沒有執(zhí)行。

可見,如果你想讓所有訂閱者都執(zhí)行處理的話,那每個(gè)訂閱者必須在訂閱程序內(nèi)自己處理好異常,不能拋出來!

4 事件-關(guān)于異步

如果事件的訂閱者中有一個(gè)是“異步”處理,又會(huì)是什么情況?

下面我們把第1個(gè)訂閱者改為異步處理,代碼如下:

instance.emd += async (sender, arg) =>
    {
        Console.WriteLine("執(zhí)行事件1!");
        await Task.Delay(1000);
        Console.WriteLine("執(zhí)行事件1!完畢");
    };

執(zhí)行后輸出如下:
執(zhí)行事件1!

執(zhí)行事件2!

執(zhí)行事件1!完畢

可見,異步的事件處理沒有阻塞進(jìn)程,很好的起到了異步方法的作用。

5 委托-Func與Action

本文最開始探討委托,然后直接順到了事件的相關(guān)話題上。其實(shí),關(guān)于委托還有一個(gè)重點(diǎn)話題漏掉了,那就是Func與Action。

在委托delegate出現(xiàn)了很久以后,微軟的.NET設(shè)計(jì)者們終于領(lǐng)悟到,其實(shí)所有的委托定義都可以歸納并簡(jiǎn)化成只用Func與Action這兩個(gè)語法糖來表示。其中,F(xiàn)unc代表有返回值的委托,Action代表無返回值的委托。有了它們兩,我們以后就不再需要用關(guān)鍵字delegate來定義委托了。

同時(shí),若再用lambda表達(dá)式取代被委托指向的具體方法,則整個(gè)委托的“定義+賦值”兩步將大大簡(jiǎn)化(lambda表達(dá)式本來也是方法定義的一種簡(jiǎn)化形式)。

下面,把最開始委托章節(jié)中關(guān)于加減法的程序代碼,用Func與lambda表達(dá)式進(jìn)行簡(jiǎn)化改造,改造后的代碼如下:

//示例:將委托/方法當(dāng)參數(shù)傳遞
        public static int Test(Func<int, int, int> MD)
        {
            return MD(10, 20);
        }

        static void Main(string[] args)
        {
            int a, b, x, y;

            Func<int, int, int> md;

            //將委托指向加法,并進(jìn)行相關(guān)操作
            md = (t, v) => t + v;
            a = md(1, 2);
            b = Test(md);

            //再將委托指向減法,并進(jìn)行相關(guān)操作
            md = (t, v) => t - v;
            x = md(7, 2);
            y = Test(md);

            Console.WriteLine($"1+2={a},10+20=,7-2={x},10-20={y}");
            Console.ReadLine();
        }

是不是代碼大大簡(jiǎn)化了?簡(jiǎn)化了哪些內(nèi)容,你可以前后對(duì)比一下...

以上就是詳解C#中delegate/event/EventHandler/Action/Func的使用和區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于C# delegate event EventHandler Action Func的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中Mutex對(duì)象用法分析

    C#中Mutex對(duì)象用法分析

    這篇文章主要介紹了C#中Mutex對(duì)象用法,結(jié)合實(shí)例形式分析了Mutex對(duì)象的功能與線程操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • c#實(shí)現(xiàn)用SQL池,多線程定時(shí)批量執(zhí)行SQL語句的方法

    c#實(shí)現(xiàn)用SQL池,多線程定時(shí)批量執(zhí)行SQL語句的方法

    構(gòu)建SQL池,分離業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層,讓業(yè)務(wù)邏輯層從低效的數(shù)據(jù)庫操作解脫,以提高系統(tǒng)整體性能
    2013-10-10
  • C# WebApi 路由機(jī)制剖析

    C# WebApi 路由機(jī)制剖析

    這篇文章主要介紹了C# WebApi 路由機(jī)制剖析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • C#實(shí)現(xiàn)將HTML網(wǎng)頁或HTML字符串轉(zhuǎn)換為PDF

    C#實(shí)現(xiàn)將HTML網(wǎng)頁或HTML字符串轉(zhuǎn)換為PDF

    將HTML轉(zhuǎn)換為PDF可實(shí)現(xiàn)格式保留、可靠打印、文檔歸檔等多種用途,滿足不同領(lǐng)域和情境下的需求,所以本文就來介紹一下如何使用C#實(shí)現(xiàn)將HTML網(wǎng)頁或HTML字符串轉(zhuǎn)換為PDF,有需要的可以參考下
    2024-01-01
  • 實(shí)例講解C#中的職責(zé)鏈模式

    實(shí)例講解C#中的職責(zé)鏈模式

    這篇文章主要介紹了C#中的職責(zé)鏈模式的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案

    C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案

    這篇文章主要介紹了C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • C# 9 中新加入的關(guān)鍵詞 init,record,with

    C# 9 中新加入的關(guān)鍵詞 init,record,with

    這篇文章主要介紹了C# 9 中新加入的關(guān)鍵詞 init,record,with的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c# 9,感興趣的朋友可以了解下
    2020-08-08
  • C#圖片處理類分享

    C#圖片處理類分享

    這篇文章主要為大家分享了C#圖片處理類的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • C#同步、異步遠(yuǎn)程下載文件實(shí)例

    C#同步、異步遠(yuǎn)程下載文件實(shí)例

    使用C#下載一個(gè)Internet上的文件主要是依靠HttpWebRequest/HttpWebResonse和WebClient。具體處理起來還有同步和異步兩種方式,所以我們其實(shí)有四種組合
    2014-04-04
  • C#中使用閉包與意想不到的坑詳解

    C#中使用閉包與意想不到的坑詳解

    這篇文章主要給大家介紹了關(guān)于C#中使用閉包與意想不到的坑,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論

高雄市| 七台河市| 沙坪坝区| 进贤县| 东莞市| 太原市| 恩平市| 那曲县| 乌苏市| 阜康市| 中西区| 宁安市| 澎湖县| 黑水县| 商水县| 兰考县| 柘荣县| 丰台区| 华亭县| 眉山市| 万州区| 濮阳市| 余姚市| 中超| 刚察县| 内黄县| 伊宁县| 莆田市| 山阴县| 达州市| 同江市| 蒙山县| 沈阳市| 双峰县| 浑源县| 肇庆市| 临洮县| 顺义区| 大庆市| 田林县| 广平县|