c# delegate和event的使用說(shuō)明
delegate是什么
委托(delegate) 是存有對(duì)某個(gè)方法的引用的一種引用類型變量,引用可在運(yùn)行時(shí)被改變。如果不好理解,可以把委托理解成為函數(shù)指針,但它們是有區(qū)別的。
delegate和C++中的函數(shù)指針:
函數(shù)指針只能指向靜態(tài)函數(shù),而delegate既可以引用靜態(tài)函數(shù),又可以引用非靜態(tài)成員函數(shù)。在引 用非靜態(tài)成員函數(shù)時(shí),delegate不但保存了對(duì)此函數(shù)入口指針的引用,而且還保存了調(diào)用此函數(shù)的類實(shí)例的引用。
其次,與函數(shù)指針相 比,delegate是面向?qū)ο?、類型安全、可靠的受控(managed)對(duì)象。也就是說(shuō),runtime能夠保證delegate指向一個(gè)有效的方法, 你無(wú)須擔(dān)心delegate會(huì)指向無(wú)效地址或者越界地址。
實(shí)例化委托:一旦聲明了委托類型,委托類型必須要通過(guò)new關(guān)鍵字來(lái)創(chuàng)建(相當(dāng)于面向?qū)ο笾械膶?shí)例化一個(gè)對(duì)象),當(dāng)創(chuàng)建委托時(shí),傳遞到new語(yǔ)句中的參數(shù)就像方法的調(diào)用一樣書寫, 但是不帶參數(shù)。
// 委托的聲明 public delegate void PrintSting(string s); //實(shí)例化委托 PrintSting ps=new PrintString(WriteToScreen);
匿名方法:
本來(lái)委托定義(聲明)好之后,還得再單獨(dú)定義委托需要使用的方法。比如你定義了一個(gè)計(jì)算器的委托, 你還需要重新寫計(jì)算加減乘除的方法了來(lái)供計(jì)算器委托來(lái)使用。這時(shí)候我們就想到了匿名方法。
用匿名方法就不需要再單獨(dú)寫加減乘除這些方法了,只需要在匿名方法的方法體內(nèi)實(shí)現(xiàn)這些邏輯就好了。例子如下:
delegate int calculator(int x, int y); //委托類型 static void Main(string[] args) { //創(chuàng)建委托對(duì)象(確定與哪些方法進(jìn)行綁定),委托實(shí)例名=new 委托名(某個(gè)類的方法,本例與加法向綁定 calculator Adding =delegate( int x, int y){ return x+y; }; calculator Moveing = delegate(int x, int y){ return x - y; }; calculator Multiply = delegate(int x, int y) { return x * y; }; calculator Divide = delegate(int x, int y) { return x / y; }; Adding(4, 4);//8 Moveing(4, 4);//0 Multiply(4, 4);//16 Divide(4, 4);//1 }
event是什么
我們可以把事件編程簡(jiǎn)單地分成兩個(gè)部分:事件發(fā)生的類(發(fā)布器:publisher)和事件接收處理的類(訂閱器:subscriber)。事件使用 發(fā)布-訂閱(publisher-subscriber) 模型。
事件發(fā)生的類就是說(shuō)在這個(gè)類中觸發(fā)了一個(gè)事件,但這個(gè)類并不知道哪個(gè)個(gè)對(duì)象或方法將會(huì)加收到并處理它觸發(fā)的事件。所需要的是在發(fā)送方和接收方之間存在一個(gè)媒介。
這個(gè)媒介在.NET Framework中就是委托(delegate)。
在事件接收處理的類中,我們需要有一個(gè)處理事件的方法。
public class A { public delegate void EventHandler(object sender); public event EventHandler a; public void Run() { Console.WriteLine("Trigger an event."); a(this); } } class B { public B(A a) { a.a += new A.EventHandler(this.b); } private void b(object sender) { Console.WriteLine("Received and handled an event." ); Console.Read(); } }
event和delegate的差異
event是一種特殊的delegate。同為public類型,對(duì)于delegate,我們?cè)诙x它的類外,不僅可以采用 += 和-=的運(yùn)算符號(hào),還可隨時(shí)調(diào)用;但是對(duì)于event,在類外只能采用 += 和-=的運(yùn)算符號(hào),不能調(diào)用,也就是event把它本身的invoke函數(shù)和括號(hào)調(diào)用的函數(shù)變成擁有這個(gè)event類的私有函數(shù)。
event
event只能被本類調(diào)用,其他的即使該類的派生類也不行,如果非要調(diào)用類內(nèi)部的event,可以先聲明一個(gè)方法,在該方法中調(diào)用event。
Action
Action是一個(gè)泛型的委托,其內(nèi)部即使用delegate去實(shí)現(xiàn),當(dāng)普通的delegate定義的參數(shù)與Action個(gè)數(shù)、類型一致時(shí),兩者實(shí)現(xiàn)的功能是一樣的。只是Action的方式更加簡(jiǎn)潔、規(guī)范。
Action與delegate更重要的一個(gè)區(qū)別在于泛型,即Action的內(nèi)部使用了泛型+委托,且泛型的方法的參數(shù)個(gè)數(shù)可擴(kuò)展到16個(gè)。微軟.net corefx中定義的Action內(nèi)部代碼如下:
namespace System { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes")] public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
解析OpenXml?Pptx的邊框虛線轉(zhuǎn)為WPF的邊框虛線問(wèn)題
這篇文章主要介紹了OpenXml?Pptx的邊框虛線轉(zhuǎn)為WPF的邊框虛線,在文中用PPTX的7種直線,分別設(shè)置7種能夠設(shè)置的虛線類型,具體實(shí)例代碼跟隨小編一起看看吧2021-12-12C#實(shí)現(xiàn)窗體淡入淡出效果的方法總結(jié)
C#實(shí)現(xiàn)窗體淡入淡出效果的方法總結(jié),需要的朋友可以參考一下2013-05-05Unity中 ShaderGraph 實(shí)現(xiàn)旋渦傳送門效果入門級(jí)教程(推薦)
通過(guò)Twirl 旋轉(zhuǎn)節(jié)點(diǎn)對(duì)Gradient Noise 梯度噪聲節(jié)點(diǎn)進(jìn)行操作,就可得到一個(gè)旋轉(zhuǎn)的旋渦效果。具體實(shí)現(xiàn)代碼跟隨小編一起通過(guò)本文學(xué)習(xí)下吧2021-07-07C#實(shí)現(xiàn)向指定文本文件添加內(nèi)容的方法
這篇文章主要介紹了C#實(shí)現(xiàn)向指定文本文件添加內(nèi)容的方法,涉及C#操作文本文件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04C#實(shí)現(xiàn)一個(gè)控制臺(tái)的點(diǎn)餐系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)一個(gè)控制臺(tái)的點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11C#調(diào)用C類型dll入?yún)閟truct的問(wèn)題詳解
這篇文章主要給大家介紹了關(guān)于C#調(diào)用C類型dll入?yún)閟truct問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03解決unity rotate旋轉(zhuǎn)物體 限制物體旋轉(zhuǎn)角度的大坑
這篇文章主要介紹了解決unity rotate旋轉(zhuǎn)物體 限制物體旋轉(zhuǎn)角度的大坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04