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#的认知。

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

注:此文章为原创,任何形式的转载都请联系做者得到受权并注明出处!
若您以为这篇文章还不错,请点击下方的推荐】,很是感谢!

 

相关文章
相关标签/搜索