C#語法——事件,逐漸邊緣化的大哥。

事件是C#的基礎之一,學好事件對於瞭解.NET框架大有好處。html

事件最多見的比喻就是訂閱,即,若是你訂閱了個人博客,那麼,當我發佈新博客的時候,你就會獲得通知。前端

而這個過程就是事件,或者說是事件運行的軌跡。編程

事件是發散,以個人博客爲核心,向全部訂閱者發送消息。咱們把這種發散稱之爲[多播]。架構

最多見的事件用途是窗體編程,在Windows窗體應用程序和WPF應用程序中。框架

當在窗體中點擊按鈕,移動鼠標等事件時,相應的後臺程序會收到通知,再執行代碼。async

事件的定義函數

官方對事件的說明是這樣的:類或對象能夠經過事件向其餘類或對象通知發生的相關事情。學習

換成正常語言就是,事件能夠定義成靜態的或普通的,因此事件就能夠由聲明的對象調用,也能夠直接經過類調用靜態事件。spa

事件是C#中的一種類型,除了框架爲咱們定義好的事件外,咱們還能夠自定義事件,用event關鍵字來聲明。設計

下面咱們來看最基礎的事件定義。

public delegate void TestDelegate(string message);                                                  
public event TestDelegate testEvent;

咱們首先定義了一個委託,而後利用event關鍵字,定義一個事件。

總體上看,好像就是在定義一個委託,只是在委託的定義以前,加了個event關鍵字。

沒錯,事件的定義就是這樣,由於要聲明一個事件,須要兩個元素:

一,標識提供對事件的響應的方法的委託。

二,一個類,用存儲事件的數據。即,事件要定義在類中。

下面咱們來爲這個事件賦值。

public void Init()
{   
    testEvent += new TestDelegate(EventSyntax_testEvent); 
    testEvent += EventSyntax_testEvent; 
}
private void EventSyntax_testEvent(string message)
{
    Console.WriteLine(message);
}

如代碼所示,咱們使用了+=這個符號來爲事件賦值,賦值的內容是一個委託和一個函數。

其中+=咱們將他理解爲【添加】。

代碼中,咱們使用兩種賦值模式,但實際上都是爲事件testEvent添加一個委。

第二種將函數直接【添加】到事件中,編譯時也會把函數轉換成委託【添加】到事件中。

系統提供事件

C#的框架都很經典,而每一個經典框架都爲咱們提供了一些經典事件。

因爲事件必須[標識響應方法的委託],因此這些事件所使用的委託都有一個共同的特色,命名中包含Event。

好比EventHandler,CancelEventHandler,RoutedEventHandler,ContextMenuEventHandler等。

其中最經典的就是EventHandler和RoutedEventHandler。

EventHandler:

EventHandler定義以下

[SerializableAttribute]
[ComVisibleAttribute(true)]
public delegate void EventHandler(
	object sender,
	EventArgs e
)

他包含了兩個參數,即當咱們爲事件添加EventHandler委託後,再去觸發該事件;被觸發的委託將獲得object sender和EventArgs e兩個參數。

sender:表明源,即觸發該事件的控件。

e:表明事件參數,即觸發該事件後,事件爲被觸發的委託,傳遞了一些參數,以方便委託在處理數據時,更便捷。

根據這個原理,咱們能夠分析出不少東西。

好比,當控件DataGrid的事件被觸發時,只要查看一下sender的真實類型,就能夠知道,究竟是DataGrid觸發的事件,仍是DataGridRow或DataGridCell觸發的了。

RoutedEventHandler:

RoutedEventHandler即路由事件,他的定義以下

public delegate void RoutedEventHandler(
	Object sender,
	RoutedEventArgs e
)

RoutedEventHandler也爲咱們提供了sender和e兩個參數。

但RoutedEventHandler特別之處是,他的sender並不必定是真實的源,由於他是一個冒泡路由事件,即上升事件。

這裏若是你們有好奇心去看官方文檔,那麼會在相關的介紹中看到兩個單詞sender和source。

經過這兩個單詞,咱們會清晰的瞭解路由事件。簡單描述一下sender和source,它們一個是發送者,一個是源。

在EventHandler中,sender即source,由於它是直接事件。而在冒泡事件中,sender不必定等於source。即發送者不必定是源。

下面咱們用WPF來看看路由事件。

咱們首先在XAML頁面定義一個RadioButton按鈕,而後設置他的模板是Button。而後分別定義各自的Click方法。

Xaml頁面以下:

 <RadioButton Click="btnParent_Click">
            <RadioButton.Template>
                <ControlTemplate>
                    <StackPanel>
                        <TextBlock Text="個人名字" ></TextBlock>
                        <Button Content="Kiba518"   Click="btnClild_Click" ></Button>
                    </StackPanel>
                </ControlTemplate>
            </RadioButton.Template> 
</RadioButton> 

cs文件事件以下:

 private void btnParent_Click(object sender, RoutedEventArgs e)
 {
     string type = sender.GetType().ToString();//RadioButton
 }

 private void btnClild_Click(object sender, RoutedEventArgs e)
 {
     string type = sender.GetType().ToString();//Button
 }

運行起來,咱們點擊按鈕,經過斷點咱們能夠看到,咱們點擊的按鈕觸發了btnClild_Click和btnParent_Click事件

順序是先btnClild_Click後btnParent_Click。

經過獲取sender的類型,我也能夠看到,btnClild_Click的sender類型是Button,而btnParent_Click的sernder類型是RadioButton。

事件驅動編程

事件驅動編程這個概念給個人感受很怪,由於一直用C#,而C#的不少框架都是事件驅動的,因此一直以爲事件驅動是理所固然。

而當事件驅動設計這個詞常常出現後,反而感受怪怪的。

就好像,每天吃大米飯,忽然有一天,全部人都說大米飯好香的感受同樣,你一聽就感受怪怪的。

由於事件驅動對於C#開發而言,實在太普通了。固然,這也得益於微軟框架作的實在是太好了。

因此,我也不知道如何在C#裏講事件驅動編程。由於使用C#的框架就是使用事件驅動編程。

事件和委託究竟是什麼關係?

事件是用來多播的,而且用委託來爲事件賦值,能夠說,事件是基於委託來實現的。

但委託中也有多播,那爲何要單獨弄出來一個事件呢?

首先,存在即合理,事件必定有他存在的意義。 

事件存在的意義

我對事件存在的意義是這樣理解的。咱們在C#編寫框架時,幾乎不用委託的多播,由於委託的多播和事件存在嚴重的二義性。雖然編寫框架的人學會了使用委託的多播,但使用框架的同事可能並還不太熟練,並且C#框架中,大可能是使用事件來進行多播的。

因此委託的多播和事件一塊兒使用的框架,會形成使用這個框架的初級開發者不少困惑,而這種困惑,會產生不少沒必要要的問題。

好比, 你定義了一個委託,另外一個開發者用這個委託作了個多播,當第三個開發者來維護這段代碼時,若是他是新手,不瞭解委託的多播,那就頗有可能只修改了委託調用的代碼。而沒有去同步多播這個委託的代碼。那系統就產生了隱藏的bug。

那麼,事件和委託究竟是什麼關係呢?

事件與委託的確存在千絲萬縷的關係,怎麼講都是正確的。但,C#開發者只須要記住,他們倆不要緊便可。在C#事件是事件,委託是委託。二者就如同int和string同樣,沒有任何關係。

緣由很簡單,學習的過程當中儘可能下降概念混淆。並且,在C#開發中,好的架構者也一般會將事件和委託分離,因此,就認爲事件和委託沒有關係便可。

結語

其實事件很好理解,一點不復雜。我在寫這篇文章的過程當中,也沒想到什麼特別的或者說比較高級的用法。

但真實的應用場景中,個人感受是,隨着MVVM的成長,事件其實在被逐漸拋棄。雖然微軟作了不少經典的事件驅動框架。但那都是過去了。

好比WPF雖然支持事件驅動,但MVVM在WPF下的表現堪稱完美,因此WPF下的事件幾乎沒有人用了。

再好比前端的Angularjs等框架,提供了優質的MVVM使用效果,也讓新的前端設計師逐漸放棄了事件。

因此,事件在將來的編程中,極可能將不在有那麼重要的地位了。但學好事件,對於咱們理解微軟框架,仍是有很大幫助的。

C#語法——元組類型

C#語法——泛型的多種應用

C#語法——await與async的正確打開方式

C#語法——委託,架構的血液

我對C#的認知。

----------------------------------------------------------------------------------------------------

注:此文章爲原創,任何形式的轉載都請聯繫做者得到受權並註明出處!
若您以爲這篇文章還不錯,請點擊下方的推薦】,很是感謝!

 

相關文章
相關標籤/搜索