欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章徹底搞清楚c#中的委托與事件

 更新時間:2019年07月18日 08:35:21   作者:micDavid  
這篇文章主要給大家介紹了如何通過一篇文章徹底搞清楚c#中的委托與事件,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

一、什么是委托呢?

聽著名字挺抽象,確實不好理解。面試官最喜歡考察這個,而且更喜歡問:“委托和事件有何異同?”。如果對一些知識點沒有想明白,那么很容易被繞進去。研究任何事物,我們不妨從它的定義開始,委托也不例外。那么先來看c#中的委托定義,先來個例子:

public delegate void GetPacage(string code);

這個委托,看起來就是個方法簽名,取包裹,需要驗證碼。與方法簽名不同的地方,在于多了一個delegate。c#中不乏一些便利好用的語法,比如foreach、yield,每一個關(guān)鍵字背后都有一段故事。delegate的背后,又有什么故事呢?其實就是c#編譯器幫我們做了些什么事情。要知道這個,我們得看生成的IL,如何查看IL?請看下圖:

vs命令行中輸入 ildasm,會打開一個反編譯的窗口,選擇我們的程序集,如下圖:

從圖中可以看出:

1、委托的本質(zhì)就是一個密封類,這個類繼承了MulticastDelegate(多播委托)

2、委托的構(gòu)造函數(shù),有兩個參數(shù),一個類型是IntPtr,用來接收方法的,如下圖:

3、可以同步調(diào)用(Invoke),也可以異步調(diào)用 (BeginInvoke、EndInvoke)

注:

1、多播委托:一個委托可以代表多個相同簽名的方法,當(dāng)委托被調(diào)用時,這些方法會依次執(zhí)行

2、IntPtr表示窗口的時候,叫它“句柄”,表示方法時,叫它“指針”

3、異步調(diào)用:會產(chǎn)生一個線程,異步執(zhí)行

二、委托有什么用?

在js中,并沒有提委托的概念,卻有“回調(diào)”,比如ajax回調(diào)。把一個函數(shù)傳遞到另外一個函數(shù)里執(zhí)行,是非常自然的事情。但是在c#中,不能直接把方法名傳遞進去。所以創(chuàng)造了委托這么個類型。c#中的委托也是為了回調(diào)。委托有什么好處?舉個例子:皇帝頒發(fā)圣旨,得派一個大臣去。大臣到了目的地,宣讀圣旨后,這才得以執(zhí)行。這說明以下兩點:

1、委托有很好的封裝性

2、委托的實例化與它的執(zhí)行是在不同的對象中完成的

三、委托與代理

我說的代理,是指設(shè)計模式中的代理。代理與實際對象有相同的接口,委托與實際方法有相同的方法簽名。這就是它們類似的地方。無論是相同的接口,還是相同的方法簽名,其本質(zhì)是遵循相同的協(xié)議。這是它們僅存的相似點。不同點多了,如目的不同,委托只是回調(diào),而代理是對實際對象的訪問控制。

四、委托和事件

先看一段代碼:

public delegate void GetPacage(string code);
 public class Heater
 {
  public event EventHandler OnBoiled;

  public event GetPacage PackageHandler;

  private void RasieBoiledEvent()
  {

   if (OnBoiled == null)
   {
    Console.WriteLine("加熱完成處理訂閱事件為空");
   }
   else
   {
    OnBoiled(this, new EventArgs());
   }
  }
  public void Begin()
  {
   heatTime = 5;
   Heat();
   Console.WriteLine("加熱器已經(jīng)開啟", heatTime);

  }
  private int heatTime;
  private void Heat()
  {
   Console.WriteLine("當(dāng)前Heat Method線程:" + Thread.CurrentThread.ManagedThreadId);
   while (true)
   {
    Console.WriteLine("加熱還需{0}秒", heatTime);

    if (heatTime == 0)
    {
     RasieBoiledEvent();
     return;
    }
    heatTime--;
    Thread.Sleep(1000);

   }
  }
 }

這個是加熱器例子,為了研究事件,里面混合了自定義的委托和事件。我們看看第6行編譯后的代碼(紅框):

編譯器幫我們做了如下的事情:

1、生成了一個私有的委托字段

[CompilerGenerated, DebuggerBrowsable(DebuggerBrowsableState.Never)]
private GetPacage PackageHandler;

2、生成了添加和移除委托的方法

[CompilerGenerated]
public void add_PackageHandler(GetPacage value)
{
 GetPacage pacage2;
 GetPacage packageHandler = this.PackageHandler;
 do
 {
  pacage2 = packageHandler;
  GetPacage pacage3 = (GetPacage) Delegate.Combine(pacage2, value);
  packageHandler = Interlocked.CompareExchange<GetPacage>(ref this.PackageHandler, pacage3, pacage2);
 }
 while (packageHandler != pacage2);
}

這就是事件和委托的關(guān)系。有點像字段和屬性的關(guān)系。那有人說,事件是一種包裝的委托,或者特殊的委托,那么到底對不對呢?我覺得不對。比如我坐了公交車回家了,能說我是一個特殊的公交車嗎?不能說A事物擁有了B事物的能力,就說A是特殊的B。那到底該怎么描述事件和委托之間的關(guān)系呢?事件基于委托,但并非委托??梢园咽录闯晌械拇?。在使用者看來,只有事件,而沒有委托。事件是對委托的包裝,這個沒錯,到底包裝了哪些東西?

1、保護委托字段,對外不開放,所以外部對象沒法直接操作委托。提供了Add和Remove方法,供外部對象訂閱事件和取消事件

2、事件的處理方法在對象外部定義,而事件的執(zhí)行是在對象的內(nèi)部,至于事件的觸發(fā),何時何地?zé)o所謂。

五、c#鼠標(biāo)鍵盤事件

此類事件的底層實現(xiàn),一方面是消息循環(huán),另一方面是硬件中斷,或者兩者結(jié)合實現(xiàn),有空了再研究。

六、經(jīng)典面試題,貓叫、老鼠跑了,主人醒來了

public delegate void ScreamHandler();

 public class Cat
 {
  public event ScreamHandler OnScream;

  public void Scream()
  {
   Console.WriteLine("貓叫了一聲");
   OnScream?.Invoke();
  }

 }
 public class Mouse
 {
  public Mouse(Cat c)
  {
   c.OnScream += () =>
   {
    Console.WriteLine("老鼠跑了");
   };
  }
 }

 public class People
 {
  public People(Cat c)
  {
   c.OnScream += () =>
   {
    Console.WriteLine("主人醒來了");
   };
  }
 }

客戶端調(diào)用:

 Cat cat = new Cat();
 Mouse m = new Mouse(cat);
 People p = new People(cat);
 cat.Scream();

運行結(jié)果:

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 快速了解如何在.NETCORE中使用Generic-Host建立主機

    快速了解如何在.NETCORE中使用Generic-Host建立主機

    這篇文章主要介紹了如何在.NETCORE中使用Generic-Host建立主機,文中代碼非常詳細(xì),可供大家參考,感興趣的朋友不妨閱讀完
    2020-05-05
  • unity shader實現(xiàn)玻璃折射效果

    unity shader實現(xiàn)玻璃折射效果

    這篇文章主要為大家詳細(xì)介紹了unity shader實現(xiàn)玻璃折射效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • opencvsharp瑕疵檢測的實現(xiàn)示例

    opencvsharp瑕疵檢測的實現(xiàn)示例

    本文主要介紹了opencvsharp瑕疵檢測的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C#配置文件設(shè)置及應(yīng)用詳解

    C#配置文件設(shè)置及應(yīng)用詳解

    在軟件開發(fā)過程中,配置文件是常用的一個功能,用于在程序運行時調(diào)整應(yīng)用程序的行為,C# 提供了多種方式來創(chuàng)建和使用配置文件,本文將詳細(xì)介紹 C# 配置文件的創(chuàng)建、修改、讀取和寫入,以及跨平臺配置文件的應(yīng)用,需要的朋友可以參考下
    2024-06-06
  • C#簡單的向量用法實例教程

    C#簡單的向量用法實例教程

    這篇文章主要介紹了C#簡單的向量用法,需要的朋友可以參考下
    2014-07-07
  • C#使用NPOI導(dǎo)出Excel類封裝

    C#使用NPOI導(dǎo)出Excel類封裝

    這篇文章主要為大家詳細(xì)介紹了C#使用NPOI導(dǎo)出Excel類封裝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#和.NET生成和使用異步流的方法實現(xiàn)

    C#和.NET生成和使用異步流的方法實現(xiàn)

    異步流可以簡化異步文件的讀取、寫入和處理,本文主要介紹了C#和.NET生成和使用異步流的方法實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • C#使用NPOI設(shè)置Excel下拉選項

    C#使用NPOI設(shè)置Excel下拉選項

    這篇文章主要為大家詳細(xì)介紹了C#使用NPOI設(shè)置Excel下拉選項,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#調(diào)用dos窗口獲取相關(guān)信息的方法

    C#調(diào)用dos窗口獲取相關(guān)信息的方法

    這篇文章主要介紹了C#調(diào)用dos窗口獲取相關(guān)信息的方法,涉及C#調(diào)用dos窗口及進程操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • 關(guān)于C#執(zhí)行順序帶來的一些潛在問題

    關(guān)于C#執(zhí)行順序帶來的一些潛在問題

    這篇文章主要給大家介紹了關(guān)于C#執(zhí)行順序帶來的一些潛在問題,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評論