廢話一堆:網上關於委託、事件的文章有不少,一千個哈姆雷特就有一千個莎士比亞,如下內容均是本人我的看法。ide
這一小章來學習一下怎麼簡單的使用委託,瞭解一些基本的知識。函數
這裏先看一下其餘所要用到的類的信息學習
/// <summary>this
/// 函數用例spa
/// </summary>設計
public class ManyMethodClass指針
{對象
public ManyMethodClass() { }blog
/// <summary> 事件
/// 實例函數
/// </summary>
/// <param name="strmes"></param>
public void InstanceMethod(string strmes)
{
Console.WriteLine("實例函數輸出:" + strmes);
}
/// <summary>
/// 靜態函數
/// </summary>
/// <param name="strmes"></param>
public static void StaticMethod(string strmes)
{
Console.WriteLine("靜態函數輸出:" + strmes);
}
}
定義一個委託類型
public delegate void DisplayStringDelegate(string strmes);
實例化委託類型
//綁定實例函數 第一種定義方式(實例函數)
DisplayStringDelegate disstrdele_instance = new DisplayStringDelegate(newManyMethodClass().InstanceMethod);
//綁定靜態函數 第二種定義方式(靜態函數)
DisplayStringDelegate disstrdele_static = new DisplayStringDelegate(ManyMethodClass.StaticMethod);
//綁定委託實例 第三種定義方式(委託實例)
DisplayStringDelegate disstrdele_delegate = new DisplayStringDelegate(disstrdele_instance);
調用委託實例
disstrdele_instance.Invoke("Hello Word");
disstrdele_static("Hello Word");
disstrdele_delegate("Hello Word");
(ps:這裏不一樣的調用方式效果都是同樣的,在下一節會有講到)
最後讓咱們看一下最終的效果圖:
委託類型是類類型
/// <summary>
/// 委託示例類
/// </summary>
public class DelegateDemonStration
{
public DelegateDemonStration() { }
public delegate void DisplayStringDelegate(string strmes);
}
在上面的示例代碼中,咱們定義了一個委託示例類DelegateDemonStration,在DelegateDemonStration的內部咱們定義了上一節中講到的委託的類型DisplayStringDelegate,
在這裏先不談DisplayStringDelegate它定義簽名類型,先來談談它究竟是什麼樣的存在。
咱們來看一下代碼:
/// <summary>
/// 委託示例類
/// </summary>
public class DelegateDemonStration
{
public DelegateDemonStration() { }
public class DisplayStringDelegate : MulticastDelegate
{
public DisplayStringDelegate(object @object, IntPtr method){}
public virtual IAsyncResult BeginInvoke(string strmes, AsyncCallback callback, object @object);
public virtual void EndInvoke(IAsyncResult result);
public virtual void Invoke(string strmes);
}
}
當咱們定義好一個委託類型的時候,在運行時C#編譯器把【public delegate void DisplayStringDelegate(string strmes);】
編譯爲【public class DisplayStringDelegate : MulticastDelegate】
因此,各位客官只要記住 在你定義一個委託類型的時候實際上你是定義了一個類
委託實例是函數指針
先讓咱們來看一下這一小節所要用到的示例代碼(所用到的對象類型仍是上一小節的內容):
DisplayStringDelegate disstrdele = newDisplayStringDelegate(newManyMethodClass().InstanceMethod);
disstrdele += ManyMethodClass.StaticMethod;//這裏是委託類型推斷 綁定函數的一種方式 幾種方式能夠自行百度
disstrdele += new DisplayStringDelegate(ManyMethodClass.StaticMethod);
1.第一步 在咱們執行DisplayStringDelegate disstrdele = newDisplayStringDelegate(newManyMethodClass().InstanceMethod);的時候,disstrdele實例是以下圖同樣:
2.第二步 當咱們繼續執行代碼 disstrdele += ManyMethodClass.StaticMethod;的時候,請再來看圖:
這是disstrdele多指向了一個函數地址,而它的內部實現並非外表看起來這樣簡單的:
這裏簡要的說一下執行第二步的時候
L_0012:是將第一步的disstrdele實例壓入棧中
L_0013:將一個空引用壓入棧中
L_0014:加載ManyMethodClass.StaticMethod函數地址
L_001a:實例化DisplayStringDelegate委託類型,假如它叫A
L_001f:將disstrdele和A合併
L_0024:將合併好的值轉換成DisplayStringDelegate類型,而且存入L_0013中
L_0029:將L_0013賦值到disstrdele實例
(以上純屬我的理解,若有誤差請幫忙糾正,謝謝)
3.第三步 當咱們繼續執行代碼disstrdele += new DisplayStringDelegate(ManyMethodClass.StaticMethod);的時候,過程和第二步相同:
終上所述,委託實例都會指向一個函數地址,固然嘍合併事後新的委託實例寧當別論,因此 委託實例是函數指針 或者委託實例是函數指針列表
咱們來看調用的代碼:
disstrdele("Hello Word");
這裏的內容是接着上一小節的內容繼續講的,拆分開來說是爲了讓你們能看的更清楚。
看一下示意圖吧,
從這裏就能夠看出來了,雖然disstrdele 實例是合併後的委託實例,它的屁股上掛上了好多函數地址,可是執行這樣函數的入口還只是一個,那就是Delegate.Invoke(string),
若是有人要問它的Invoke(string)內部是怎麼實現的,暫時回答不了,由於具體的代碼是動態生成的吧,不過咱們能夠本身猜測或者想象一下它是怎麼實現的。
在這裏就很少說了。
看了以上的內容能大概的知道或者分清一些概念性的東西。
這裏本人只是講了一把劍是由鐵鑄成的,能夠用來切割、刺、劈、砍,至於這把劍怎麼用就因人而異了。
這一章咱們來學習一下事件
照舊咱們先來看一下示例代碼:
public class EventDomeStration
{
public EventDomeStration() { }
/// <summary>
/// 定義好的一個示例
/// </summary>
public event DisplayStringDelegate DisplayStringEventHandler;
}
在上面的代碼中,咱們定義了一個事件DisplayStringEventHandler,而在它名稱前面的是一個DisplayStringDelegate委託類型(就是咱們上一節所說的委託)。
就對於它而言來看一下MSIL,看看它到底是什麼樣的:
.class public auto ansi beforefieldinit EventDomeStration extends [mscorlib]System.Object
{
.field private class DelegateCaseAndEventCase.DisplayStringDelegate DisplayStringEventHandler
.event DelegateCaseAndEventCase.DisplayStringDelegate DisplayStringEventHandler
{
.addon instance void DelegateCaseAndEventCase.EventDomeStration::add_DisplayStringEventHandler(class DelegateCaseAndEventCase.DisplayStringDelegate)
.removeon instance void DelegateCaseAndEventCase.EventDomeStration::remove_DisplayStringEventHandler(class DelegateCaseAndEventCase.DisplayStringDelegate)
}
}
從這裏能夠看到,定義好的一個事件就是一個私有(DisplayStringDelegate委託類型)的字段加上一個事件訪問器,也就是至關於C#代碼的這樣:
public class EventDomeStration
{
public EventDomeStration() { }
private DisplayStringDelegate displaystringdele;
public event DisplayStringDelegate DisplaystringEventHandler
{
add
{
displaystringdele += value;
}
remove
{
displaystringdele -= value;
}
}
}
在這裏本人對事件的定義是:
事件就是所在對象裏的屬性,而屬性的類型是委託類型,它是負責架設與外部對象即時通信(傳遞消息)的橋樑,橋樑自己就是委託。
出門在外務工,不免要租房子住,每次找房子是件頭疼的事請各位客官一塊兒來看一下,就拿這個來舉個例子。
先定義一個委託:publicdelegatevoid消息反饋(string 反饋房子信息);
首先得有一箇中介,暫且叫它爲×××中介1, 來看一下它的內部定義:
public class ×××中介1
{
public ×××中介1() { }
public ×××中介1(string 具體要求)
{
房源信息處理(具體要求);
}
public event 消息反饋 消息通知;
public string 客戶要求的信息_1 = string.Empty;
private void 房源信息處理(string 客戶要求的信息)
{
//邏輯處理
//假如是有客戶須要的 則通知客戶
if (消息通知 != null)
{
消息通知("有房子,什麼樣的,信息等等");
}
客戶要求的信息_1 = 客戶要求的信息;
//邏輯處理要是沒有 把信息移交給了中介2
×××中介2 中介2 = new ×××中介2(this);
}
public void 其它中介消息通知(string 房子信息)
{
if (消息通知 != null)
{
消息通知(房子信息);
}
}
}
中介有了,那如今我想要開始租房子怎麼辦?不要緊,找中介。
首先先把「我」定義出來:
public class 我
{
//好比我要租房子
public 我(){ }
public void 我要租房子(string 具體的要求)
{
//找的是×××中介1
×××中介1 中介1 = new ×××中介1(具體的要求);
中介1.消息通知 += new 消息反饋(中介1_消息通知);
}
void 中介1_消息通知(string 房子信息)
{
//我能夠從【房子信息】中知道是否有有合適的房子,若是有得話,是什麼樣的
}
}
public class ×××中介2
{
public string 客戶要求信息 = string.Empty;
public ×××中介2() { }
public ×××中介2(×××中介1 中介1)
{
房源信息處理(中介1);
}
private void 房源信息處理(×××中介1 中介1)
{
//邏輯處理
//判斷是否有知足 ->中介1.客戶要求的信息_1值條件的房源
//若是有
中介1.其它中介消息通知("房子有的,房子的信息等等");
}
}
上面定義了 我、×××中介1、×××中介2,如今 我 要找房子了
我 me = new 我();
me.我要租房子("有牀就行");
好了,「我」已經把信息發佈出去了,如今就坐等×××中介1的通知了。
由於事件只能是對象自己內部觸發,這個設計是合理,爲何不能用委託,委託也能夠實現一樣的功能啊?
假如用了委託,這個例子的意思就是「我」能夠控制×××中介1有沒有找到房子信息,這個是不符合常理的。
由於「我」是找的×××中介1,×××中介1根據「我」的要求沒找到,把這個信息交給了×××中介2,讓×××中介2幫忙找找,而後中×××中介2找到了,
可是中×××中介2並不能直接通知「我」,若是能夠直接通知的話,這樣「我」會告×××中介1侵犯客戶隱私,
因此只能是×××中介2告訴×××中介1找到了【也就是代碼:×××中介1.其它中介消息通知("房子有的,房子的信息等等");】,而後再由×××中介1來通知「我」。