C 基礎知識系列 專題四 事件揭秘

2022-03-01 02:18:18 字數 3702 閱讀 9786

**

引言:

前面幾個專題對委託進行了詳細的介紹的,然後我們在編寫**過程中經常會聽到「事件」這個概念的,尤其是寫ui的時候,當我們點選乙個按鈕後vs就會自動幫我們生成一些後台的**,然後我們就只需要在click方法裡面寫**就可以,所以可能有些剛接觸c#的朋友就覺得這樣很理所當然的,也沒有去思考這是為什麼的,為什麼點選下事件就會觸發我們在click方法裡面寫的**呢?事件到底扮演個什麼樣的角色呢?為了解除大家的這些疑惑,下面就詳細介紹了事件,讓一些初學者深入理解c#中的事件的概念。

一、為什麼c#中會有事件的?

前面專題中介紹了我理解的為什麼需要委託的,所以這裡我來分享下我理解的為什麼c#中要引入事件這個概念的。下面就簡單講講生活中事件的例子的,最近我生日剛過完的,我就以生日這個話題要談談的,日子一天天的過去,當生日的日期到的時候,這時候就觸發了生日事件的,此時過生日的人就是觸發生日事件的物件的,然後有些關係你的朋友就會對這個事件進行關注,一旦這個事件觸發, 他們就可能會陪你一起慶祝生日,然後送禮物給你,當然並不是所有人都會對你的生日關注的,有些人肯定根本就不知道的, 只有對於你生日事件進行了關注了的人才會送禮物給你。這樣的生活中的乙個生日過程,然而對於為什麼c#中會有事件這個概念當然就更好理解了,c#是乙個物件導向的語言,我們使用c#語言進行編碼也是為了用**幫助我們完成現實生活中的事情的,所以當然也就必須有事件來反映生活中發生事情的情況了。

二、自己如何實現乙個事件模式的?

現在我們知道了為什麼c#要引入事件了,但是對於我們在**中使用的事件大部分都是.net類庫為我們提供的,例如控制項的各種事件,我們只需要點選按鈕後就會觸發點選事件的,但是我們很想理解這個事件是如何觸發的,我們是否可以自己定義實現事件模式的乙個程式的呢?答案當然是可以的,下面就以上面生日的例子來通過**來解釋下如何實現乙個事件模式的。

具體**為:

using system;

using system.threading;

namespace birthdayeventdemo

}// 第一步: 定義乙個型別用來儲存所有需要傳送給事件接收者的附加資訊

public class birthdayeventargs : eventargs

}public birthdayeventargs(string name)

}// 第二步:定義乙個生日事件,首先需要定義乙個委託型別,用於指定事件觸發時被呼叫的方法型別

public delegate void birthdayeventhandle(object sender, birthdayeventargs e);

// 定義事件成員

public class subject}}

// 定義觸發事件的物件,事件源

public class me : subject

public void timeup()

}// 好友物件

public class friend1

}public class friend2}}

執行結果為:

三、編譯器是如何解釋事件的呢?

上面我們已經介紹了如何去實現自己去實現乙個事件模式的,大家可以展開**來具體的檢視的,實現過程主要是——定義觸發物件的事件源(指的是誰過生日)->定義關注你生日事件的朋友物件-> 方法登記對事件的關注,當事件觸發時通知登記的方法被呼叫。然而相信大家還有有疑問——到底c#中的事件是什麼呢?編譯器又是如何去解釋它的?下面就為大家解除下疑惑的:

首先事件其實就是委託的(確切的說事件就是委託鏈),從上面的**中,我們定義的事件除了使用event關鍵字外,還用到了乙個委託型別,然而委託是乙個類,類肯定就有屬性欄位的,然而我們就可以把事件理解為委託的乙個屬性,屬性的返回值是乙個委託型別。說事件是委託的乙個屬性,是有根據的,我們通過中間語言**可以知道編譯器是如何去解釋我們定義的事件的。

// 第二步:定義乙個生日事件,首先需要定義乙個委託型別,用於指定事件觸發時被呼叫的方法型別

public delegate void birthdayeventhandle(object sender, birthdayeventargs e);

// 定義生日事件

public event birthdayeventhandle birthdayevent;

// 1. 乙個被初始化為null的私有委託字段

private birthdayeventhandle birthdayevent =null;

//2. 乙個公共add_birthdayevent方法

public void add_birthdayevent(birthdayeventhandle value)

// 3. 乙個公共的remove_birthdayevent方法

public void remove_birthdayevent(birthdayeventhandle value)

第一段**乙個委託的私有字段,該字段是對乙個委託列表的頭部的引用,事件發生時會通知這個列表中的委託。字段初始化為null,表明無關注人登記了對事件的關注。

第二段**是乙個以add為字首的方法,該方法是由編譯器自動命名的,**內容呼叫delegate.combine方法將委託例項新增到委託列表中,返回新的列表位址,並將這個位址存回字段。

第三段**也是乙個方法,它使得乙個物件登出對事件的關注,同樣的方法體呼叫delegate.remove方法將委託例項從委託列表中刪除,返回新的列表位址,並將這個位址存回字段中。(注,如果試圖刪除乙個從未新增過的方法,delegate.remove方法在內部將不做任何事情,也就是說,不會丟擲任何一次,也不會顯示任何警告,事件的方法集合保持不變)。

同時大家也可以通過除錯來說明事件是乙個委託鏈的,大家可以在eventsource.birthdayevent+=new birthdayeventhandle(obj2.buycake);這行**設定乙個斷點除錯的,下面是我除錯過程中的乙個截圖,大家也可以自己除錯看看的,這樣將會更加理解事件是乙個委託鏈的概念:

按f10執行一行後的截圖

通過上面的截圖,相信大家對於事件是乙個委託鏈的概念相信會有進一步的理解的。

四、小結

到這裡本專題的內容也就介紹完了, 希望通過本專題,大家可以對事件有進一步的理解,理解事件與委託之間的關係。這個專題通過自己實現的乙個事件模式裡解釋事件的本質,然而我們經常使用的是net類庫中定義好的事件,然而有些剛接觸c#的人卻不理解net中定義的事件背後所做的事情,只是知道點下按鈕後在click方法裡面寫入自己的一些控制**,然而背後的過程具體是怎樣的,既然事件是委託,那麼click事件是委託型別,其中的委託型別又是怎麼被例項化的呢?這些內容將在下乙個專題給大家分享下的。

C 基礎知識系列 專題十六 Linq介紹

本專題概要 引言 終於到了c 3中最重要特性的介紹了,可以說之前所有介紹的特性都是為了linq而做準備的,然而要想深入理解linq並不是這個專題可以介紹完的,所以我打算這個專題將對linq做乙個簡單的介紹,對於linq的深入理解我將會後面單獨作為乙個系列要和大家分享下。一 linq是什麼?linq也...

事件基礎知識

什麼是事件 是物件內部狀態發生了變化,或者物件做某些動作時 或做之前,做之後 向外界發出的通知。註冊時間的基本形式 1註冊事件偵聽器 處理事件的物件.addeventlistener 事件型別,偵聽器函式 2定義事件偵聽器 function 偵聽器函式 e 事件類 void 預設為void 此處為響...

c 基礎知識整理(四)

一 explicit pragma once include class explicit test explicit test operator const explicit test other 不帶explicit 測試結果 explicit test aa 5 直接隱式轉換,可以傳乙個引數是...