欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

1 委托

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

(1)將方法當作參數傳遞

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

下面,給出一個展現了上述兩大作用的委托代碼示例:

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

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

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

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

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

            MyDelegate md;

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

            //再將委托指向Reduce這個方法,并進行相關操作
            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í)行以上程序,輸出結果如下:

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

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

//定義一個委托
        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

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

為了解決這個弊端,事件event應運而生。

2 事件-概念的引出

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

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

下面是定義一個事件的代碼:

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

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

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

//使用
public event EventHandler emd;

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

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();
        }

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

這里模擬了2個訂閱者,分別處理報警事件emd。

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

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

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

3 事件-關于異常

現在,我們在第一個訂閱者中加入異常,如下:

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

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

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

4 事件-關于異步

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

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

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

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

執(zhí)行事件2!

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

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

5 委托-Func與Action

本文最開始探討委托,然后直接順到了事件的相關話題上。其實,關于委托還有一個重點話題漏掉了,那就是Func與Action。

在委托delegate出現了很久以后,微軟的.NET設計者們終于領悟到,其實所有的委托定義都可以歸納并簡化成只用Func與Action這兩個語法糖來表示。其中,Func代表有返回值的委托,Action代表無返回值的委托。有了它們兩,我們以后就不再需要用關鍵字delegate來定義委托了。

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

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

//示例:將委托/方法當參數傳遞
        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;

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

            //再將委托指向減法,并進行相關操作
            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();
        }

是不是代碼大大簡化了?簡化了哪些內容,你可以前后對比一下...

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

相關文章

  • 詳解ASP.NET中Identity的身份驗證代碼

    詳解ASP.NET中Identity的身份驗證代碼

    這篇文章主要介紹了ASP.NET Identity 的“多重”身份驗證代碼,以及實現的原理講解,需要的朋友參考一下。
    2017-12-12
  • C#常用正則驗證函數示例

    C#常用正則驗證函數示例

    這篇文章主要介紹了C#常用正則驗證函數,舉例分析了C#針對IP驗證、價格驗證及正整數驗證的相關操作技巧,需要的朋友可以參考下
    2017-01-01
  • datatable生成excel和excel插入圖片示例詳解

    datatable生成excel和excel插入圖片示例詳解

    excel導出在C#代碼中應用己經很廣泛了,下面講了datatable生成excel、復制sheet頁、刪除sheet頁、選中sheet頁、另存excel文件、excel中插入圖片等功能
    2014-01-01
  • 適合初學者開發(fā)的C#在線英漢詞典小程序

    適合初學者開發(fā)的C#在線英漢詞典小程序

    這篇文章主要為大家詳細介紹了適合初學者開發(fā)的C#在線英漢詞典小程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • C#中判斷、驗證字符串是否為日期格式的實現代碼

    C#中判斷、驗證字符串是否為日期格式的實現代碼

    這篇文章主要介紹了C#中判斷、驗證字符串是否為日期格式的實現代碼,使用DateTime類中自帶的兩個方法實現,需要的朋友可以參考下
    2014-08-08
  • C#中的checksum計算公式

    C#中的checksum計算公式

    這篇文章主要介紹了C#中的checksum計算公式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • C#二維碼圖片識別代碼

    C#二維碼圖片識別代碼

    這篇文章主要為大家詳細介紹了C#二維碼圖片識別代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 詳解C#中SqlParameter的作用與用法

    詳解C#中SqlParameter的作用與用法

    本篇文章主要介紹了C#中SqlParameter的作用與用法,因為通過SQL語句的方式,有時候存在腳本注入的危險,所以在大多數情況下不建議用拼接SQL語句字符串方式,希望通過SqlParameter實現來實現對數據的操作。
    2016-12-12
  • C#通過屬性名稱獲取(讀取)屬性值的方法

    C#通過屬性名稱獲取(讀取)屬性值的方法

    本文主要介紹了C#通過屬性名稱獲取(讀取)屬性值的方法,并提供了簡化版代碼,具有很好的參考價值,需要的朋友可以看下
    2016-12-12
  • C#中GridView動態(tài)添加列的實現方法

    C#中GridView動態(tài)添加列的實現方法

    這篇文章主要介紹了C#中GridView動態(tài)添加列的實現方法,涉及C#中GridView的相關使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07

最新評論