五月天六月婷婷开心激情,天使的性电影,三级韩国一区久久二区综合,五月婷婷久,九九精品在线视频,66精品综合久久久久久久

您的位置:首頁 >資訊 >

徹底弄懂C#中delegate、event、EventHandler、Action、Func的使用和區別

2023-04-03 10:09:21 博客園
【目錄】1 委托2事件-概念的引出3事件-關于異常4事件-關于異步5委托-Func與Action1 委托

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


(相關資料圖)

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

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

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

//定義一個委托        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={b},7-2={x},10-20={y}");            Console.ReadLine();        }

執行以上程序,輸出結果如下:

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

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

//定義一個委托        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={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在定義類中(發布者)是可以直接=的,但是在其他類中(訂閱者)就只能+= -=了,也就是說發布者發布一個事件后,訂閱者針對他只能進行自身的訂閱和取消。

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

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

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

//@sender: 引發事件的對象//@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("執行事件1!");            };            instance.emd += (sender, arg) =>            {                Console.WriteLine("執行事件2!");            };            instance.RaiseEvent();            Console.ReadLine();        }

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

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

程序執行結果如下:

執行事件1!

執行事件2!

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

3事件-關于異常

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

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

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

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

4事件-關于異步

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

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

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

執行后輸出如下:執行事件1!

執行事件2!

執行事件1!完畢

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

5委托-Func與Action

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

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

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

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

//示例:將委托/方法當參數傳遞        public static int Test(Func MD)        {            return MD(10, 20);        }        static void Main(string[] args)        {            int a, b, x, y;            Func 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={b},7-2={x},10-20={y}");            Console.ReadLine();        }

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

標簽:


        
精彩推薦

 

主站蜘蛛池模板: 8x视频在线观看| 国产精品久久久久久久久电影网 | 一级二级三级黄色片| 免费看男阳茎进女阳道动态图| 国产**aa全黄毛片| 夜夜躁狠去2021| 在线网站你懂得| 中文字幕黑人借宿神宫寺| 亚洲麻豆视频| 毛片免费试看| 波多野结衣精品一区二区三区| 国产精品高清尿小便嘘嘘| 久久中文字幕一区二区| 国产黄色一级毛片| 伊人久久中文大香线蕉综合| 四虎成人精品在永久免费| 久久综合九色综合97欧美| 永久看一二三四线| 日本老头变态xxxx| 妞干网视频| 2021光根影院理论片| 亚洲成年人专区| 婷婷亚洲久悠悠色悠在线播放| 成人免费看www网址入口| 拔播拔播华人永久免费| 好大的奶女好爽视频| 好男人好资源在线| 亚洲日韩中文字幕在线播放| 国产亚洲人成网站在线观看| 日本v电影| 久久99精品福利久久久| 99久久国产综合精品麻豆| 欧美国产日韩久久mv| 欧美最猛黑人xxxx黑人猛交黄| 国产乱子伦在线观看不卡| 亚洲一卡二卡三卡四卡无卡麻豆| 久久丁香五月天综合网| 免费国产成人午夜私人影视| 大伊香蕉精品一区视频在线 | 一级红色片| 国产精品va在线观看一|