中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c#中的委托與事件是什么

發布時間:2021-08-25 17:37:42 來源:億速云 閱讀:213 作者:chen 欄目:編程語言

這篇文章主要介紹“c#中的委托與事件是什么”,在日常操作中,相信很多人在c#中的委托與事件是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”c#中的委托與事件是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、什么是委托呢?

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

public delegate void GetPacage(string code);

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

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

從圖中可以看出:

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

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

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

注:

1、多播委托:一個委托可以代表多個相同簽名的方法,當委托被調用時,這些方法會依次執行

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

3、異步調用:會產生一個線程,異步執行

二、委托有什么用?

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

1、委托有很好的封裝性

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

三、委托與代理

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

四、委托和事件

先看一段代碼:

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("加熱器已經開啟", heatTime);  }  private int heatTime;  private void Heat()  {   Console.WriteLine("當前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);}

這就是事件和委托的關系。有點像字段和屬性的關系。那有人說,事件是一種包裝的委托,或者特殊的委托,那么到底對不對呢?我覺得不對。比如我坐了公交車回家了,能說我是一個特殊的公交車嗎?不能說A事物擁有了B事物的能力,就說A是特殊的B。那到底該怎么描述事件和委托之間的關系呢?事件基于委托,但并非委托。可以把事件看成委托的代理。在使用者看來,只有事件,而沒有委托。事件是對委托的包裝,這個沒錯,到底包裝了哪些東西?

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

2、事件的處理方法在對象外部定義,而事件的執行是在對象的內部,至于事件的觸發,何時何地無所謂。

五、c#鼠標鍵盤事件

此類事件的底層實現,一方面是消息循環,另一方面是硬件中斷,或者兩者結合實現,有空了再研究。

六、經典面試題,貓叫、老鼠跑了,主人醒來了

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("主人醒來了");   };  } }

客戶端調用:

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

到此,關于“c#中的委托與事件是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

句容市| 尖扎县| 白沙| 仪陇县| 柘荣县| 普兰县| 嘉善县| 台山市| 房产| 汉沽区| 西宁市| 云林县| 乌拉特前旗| 富阳市| 马公市| 会泽县| 东平县| 奉化市| 志丹县| 澄江县| 徐汇区| 丁青县| 荆州市| 包头市| 大埔县| 台中市| 江都市| 千阳县| 安平县| 阜新市| 岳池县| 綦江县| 横山县| 贵德县| 阿拉善右旗| 夏邑县| 防城港市| 凌海市| 南宁市| 中江县| 奉节县|