c# delegate和event的使用說明
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ì)象。也就是說,runtime能夠保證delegate指向一個(gè)有效的方法, 你無須擔(dān)心delegate會(huì)指向無效地址或者越界地址。
實(shí)例化委托:一旦聲明了委托類型,委托類型必須要通過new關(guān)鍵字來創(chuàng)建(相當(dāng)于面向?qū)ο笾械膶?shí)例化一個(gè)對(duì)象),當(dāng)創(chuàng)建委托時(shí),傳遞到new語句中的參數(shù)就像方法的調(diào)用一樣書寫, 但是不帶參數(shù)。
// 委托的聲明 public delegate void PrintSting(string s); //實(shí)例化委托 PrintSting ps=new PrintString(WriteToScreen);
匿名方法:
本來委托定義(聲明)好之后,還得再單獨(dú)定義委托需要使用的方法。比如你定義了一個(gè)計(jì)算器的委托, 你還需要重新寫計(jì)算加減乘除的方法了來供計(jì)算器委托來使用。這時(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是什么
我們可以把事件編程簡單地分成兩個(gè)部分:事件發(fā)生的類(發(fā)布器:publisher)和事件接收處理的類(訂閱器:subscriber)。事件使用 發(fā)布-訂閱(publisher-subscriber) 模型。
事件發(fā)生的類就是說在這個(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的方式更加簡潔、規(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)文章
使用C#實(shí)現(xiàn)對(duì)任意區(qū)域任意大小的截圖
這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)簡單的截圖功能,可以對(duì)任意區(qū)域任意大小的截圖,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
Chrome Visual Studio 2005下的編譯過程
研究Chrome ,首先得把它編譯出來,這對(duì)于后續(xù)的代碼分析和閱讀有很大的幫助,想想自己編譯出一個(gè) Chrome 瀏覽器來使用,那是一件很炫的事情。2009-07-07
淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別
C#靜態(tài)方法與非靜態(tài)方法的區(qū)別不僅僅是概念上的,那么他們有什么具體的區(qū)別呢?讓我們通過本文向大家介紹下C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別,一起看看吧2017-09-09
C#實(shí)現(xiàn)的封裝CURD到SqlHelper類用法簡單分析
這篇文章主要介紹了C#實(shí)現(xiàn)的封裝CURD到SqlHelper類用法,涉及數(shù)據(jù)庫相關(guān)配置方法及SqlHelper類的簡單使用技巧,代碼中包含了較為詳盡的注釋便于理解,需要的朋友可以參考下2017-11-11
使用C#實(shí)現(xiàn)在屏幕上畫圖效果的代碼實(shí)例
本篇文章是對(duì)使用C#在屏幕上畫圖效果的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

