廢話一堆:網上關于委托、事件的文章有很多,一千個哈姆雷特莎士比亞就有一千個莎士比亞,以下内容均是本人個人見解。
這一小章來學習一下怎麼簡單的使用委托,了解一些基本的知識。
這裡先看一下其他所要用到的類的資訊
///
<summary>
/// 函數用例
/// </summary>
public
class ManyMethodClass
{
public ManyMethodClass() { }
/// <summary>
/// 執行個體函數
///
</summary>
/// <param
name="strmes"></param>
public void
InstanceMethod(string strmes)
{
Console.WriteLine("執行個體函數輸出:"
+ strmes);
}
/// <summary>
/// 靜态函數
///
/// <param
public
static void
StaticMethod(string strmes)
{
Console.WriteLine("靜态函數輸出:"
}
}
定義一個委托類型
public delegate void DisplayStringDelegate(string
strmes);
執行個體化委托類型
//綁定執行個體函數 第一種定義方式(執行個體函數)
DisplayStringDelegate
disstrdele_instance = new
DisplayStringDelegate(new ManyMethodClass().InstanceMethod);
//綁定靜态函數 第二種定義方式(靜态函數)
DisplayStringDelegate disstrdele_static
= new DisplayStringDelegate(ManyMethodClass.StaticMethod);
//綁定委托執行個體 第三種定義方式(委托執行個體)
disstrdele_delegate = new
DisplayStringDelegate(disstrdele_instance);
調用委托執行個體
disstrdele_instance.Invoke("Hello
Word");
disstrdele_static("Hello Word");
disstrdele_delegate("Hello
(ps:這裡不同的調用方式效果都是一樣的,在下一節會有講到)
最後讓我們看一下最終的效果圖:
委托類型是類類型
///
委托示例類
public
class DelegateDemonStration
{
public DelegateDemonStration()
{ }
public delegate
void DisplayStringDelegate(string strmes);
}
在上面的示例代碼中,我們定義了一個委托示例類DelegateDemonStration,在DelegateDemonStration的内部我們定義了上一節中講到的委托的類型DisplayStringDelegate,
在這裡先不談DisplayStringDelegate它定義簽名類型,先來談談它到底是什麼樣的存在。
我們來看一下代碼:
public class
DisplayStringDelegate : MulticastDelegate
{
public DisplayStringDelegate(object @object, IntPtr
method){}
public virtual
IAsyncResult BeginInvoke(string
strmes, AsyncCallback callback,
object @object);
void EndInvoke(IAsyncResult
result);
void Invoke(string
strmes);
}
當我們定義好一個委托類型的時候,在運作時C#編譯器把【public
delegate void
DisplayStringDelegate(string strmes);】
編譯為【public
class DisplayStringDelegate
: MulticastDelegate】
是以,各位客官隻要記住
在你定義一個委托類型的時候實際上你是定義了一個類
委托執行個體是函數指針
先讓我們來看一下這一小節所要用到的示例代碼(所用到的對象類型還是上一小節的内容):
DisplayStringDelegate disstrdele =
new DisplayStringDelegate(new ManyMethodClass().InstanceMethod);
disstrdele
+= ManyMethodClass.StaticMethod;//這裡是委托類型推斷 綁定函數的一種方式 幾種方式可以自行百度
+= new DisplayStringDelegate(ManyMethodClass.StaticMethod);
1.第一步 在我們執行DisplayStringDelegate disstrdele =
new DisplayStringDelegate(new ManyMethodClass().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() { }
定義好的一個示例
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
.addon instance void
DelegateCaseAndEventCase.EventDomeStration::add_DisplayStringEventHandler(class
DelegateCaseAndEventCase.DisplayStringDelegate)
.removeon instance void
DelegateCaseAndEventCase.EventDomeStration::remove_DisplayStringEventHandler(class
從這裡可以看到,定義好的一個事件就是一個私有(DisplayStringDelegate委托類型)的字段加上一個事件通路器,也就是相當于C#代碼的這樣:
class EventDomeStration
public EventDomeStration() { }
private DisplayStringDelegate
displaystringdele;
public event
DisplaystringEventHandler
add
displaystringdele += value;
remove
displaystringdele -= value;
}
在這裡本人對事件的定義是:
事件就是所在對象裡的屬性,而屬性的類型是委托類型,它是負責架設與外部對象即時通訊(傳遞消息)的橋梁,橋梁本身就是委托。
出門在外務工,難免要租房子住,每次找房子是件頭疼的事請各位客官一起來看一下,就拿這個來舉個例子。
先定義一個委托:public
消息回報(string
回報房子資訊);
首先得有一個中介,暫且叫它為房産中介1,
來看一下它的内部定義:
房産中介1
public 房産中介1() {
public 房産中介1(string
具體要求)
房源資訊處理(具體要求);
消息回報
消息通知;
public string
客戶要求的資訊_1 = string.Empty;
private void
房源資訊處理(string
客戶要求的資訊)
//邏輯處理
//假如是有客戶需要的
則通知客戶
if (消息通知 != null)
{
消息通知("有房子,什麼樣的,資訊等等");
}
客戶要求的資訊_1 =
客戶要求的資訊;
//邏輯處理要是沒有
把資訊移交給了中介2
房産中介2 中介2 = new
房産中介2(this);
public void 其它中介消息通知(string
房子資訊)
if (消息通知 != null)
消息通知(房子資訊);
中介有了,那現在我想要開始租房子怎麼辦?沒關系,找中介。
首先先把“我”定義出來:
class 我
//比如我要租房子
public 我(){ }
public void 我要租房子(string
具體的要求)
//找的是房産中介1
房産中介1 中介1 = new
房産中介1(具體的要求);
中介1.消息通知 += new 消息回報(中介1_消息通知);
void 中介1_消息通知(string
//我可以從【房子資訊】中知道是否有有合适的房子,如果有得話,是什麼樣的
class 房産中介2
public string 客戶要求資訊 = string.Empty;
public 房産中介2() { }
public 房産中介2(房産中介1
中介1)
房源資訊處理(中介1);
private void 房源資訊處理(房産中介1
//邏輯處理
//判斷是否有滿足 ->中介1.客戶要求的資訊_1值條件的房源
//如果有
中介1.其它中介消息通知("房子有的,房子的資訊等等");
}
上面定義了 我、房産中介1、房産中介2,現在
我 要找房子了
我
me = new 我();
me.我要租房子("有床就行");
好了,“我”已經把資訊釋出出去了,現在就坐等房産中介1的通知了。
因為事件隻能是對象本身内部觸發,這個設計是合理,為什麼不能用委托,委托也可以實作同樣的功能啊?
假如用了委托,這個例子的意思就是“我”可以控制房産中介1有沒有找到房子資訊,這個是不符合常理的。
因為“我”是找的房産中介1,房産中介1根據“我”的要求沒找到,把這個資訊交給了房産中介2,讓房産中介2幫忙找找,然後中房産中介2找到了,
但是中房産中介2并不能直接通知“我”,如果可以直接通知的話,這樣“我”會告房産中介1侵犯客戶隐私,
是以隻能是房産中介2告訴房産中介1找到了【也就是代碼:房産中介1.其它中介消息通知("房子有的,房子的資訊等等");】,然後再由房産中介1來通知“我”。
作者:
出處:
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面