[C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情 (转载)
当我们在点击窗口中的Button控件VS会帮我们自动生成一些代码,我们只需要在Click方法中写一些自己的代码就可以实现触发Click事件后我们Click方法中代码就会执行,然而我一直有一个疑问的——既然上一专题中说事件是一个多播委托,然而自动生成的代码中只有事件的实例化,却没有看到事件的调用,那既然没有事件调用的代码,那封装的Click为什么会执行呢?
一、点击按钮时触发Click事件背后发送的事情
在引言中提出了我的提问的, 我相信有些朋友可能也会有这样的疑问的,然后事件肯定是调用了的, 只是不是我们代码中调用,而是Butoon控件的内部代码里面调用了事件,而导致委托封装的Click方法而被调用,这样才符合我们看到的情况的——我们点击按钮后,我们后台代码中的Click方法就会执行。为了明白到底背后发生了什么事情的, 让我们一起来探究个究竟吧?
我们新建一个Windows 窗体程序,然后在窗体中拖入一个Button控件并单击按钮,这时候VS为我们生成了如下的代码:

private System.Windows.Forms.Button button1;
private void InitializeComponent()
{
his.button1 = new System.Windows.Forms.Button();
this.button1.Location = new System.Drawing.Point(105, 89);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "请点击我";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
}
// 后台代码
private void button1_Click(object sender, EventArgs e)
{
}

从上面代码中我们看到VS为我们自动创建了一个Button对象并实例化,设置了它的属性并通过 this.button1.Click += new System.EventHandler(this.button1_Click);这行代码把 button1_Click注册对Click事件的关注,然而事件的调用代码在哪里呢? 下面我们就在button1_Click方法里面设置断点看看代码是如何执行的(通过查看调用堆栈来看看代码的执行顺序),下面是我设置断点的一张调用堆栈截图:

从上图中我发现在调用button1_Click方法之前要执行Control.OnClick(System.EventArgs e)方法的,然后我们用发射工具去查看下Control.OnClick(System.Eventrgs e)方法中具体有什么样的代码:OnClick方法内部代码截图为:

从反射的代码中可以明白,首先从Events(大家可以通过反射工具去查看Events的类型,它的类型为EventHandlerList,而EventHandlerList又是一个密封类)委托集合中取出委托,如果Click事件(委托)实例化了的话,此时就不为空,此时就会调用委托——handler(this, e),我们知道之前我们通过 this.button1.Click += new System.EventHandler(this.button1_Click);代码实例化了委托事件,所以此时被EventHandler封装的button1_Click方法就会执行。
通过上面的解释我已经解除了我一开始的疑惑了,事件的调用在.Net类库中的Control.OnClick方法里面调用,这也就是我说要表达的Click事件背后做的事情的
下面是反射得到的Click事件的代码截图:

二、小结
本专题首先提出我对按钮单击事件背后发生的事情的疑惑,通过调试和反射工具一步一步把疑惑接触,相信其他控件的其他事件也是如此的,本专题主要想让大家知道下.Net类库为我们做的事情的,希望一些初学者们了解知识时,要努力知道事物的本质。最后希望本专题可以让大家更进一步的理解事件的本质的,我将下一专题和大家分享下我理解的泛型到底是怎样的。
[C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情 (转载)的更多相关文章
- [C# 基础知识系列]专题一:深入解析委托——C#中为什么要引入委托
转自http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html 引言: 对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不 ...
- [C# 基础知识系列]专题九: 深入理解泛型可变性
引言: 在C# 2.0中泛型并不支持可变性的(可变性指的就是协变性和逆变性),我们知道在面向对象的继承中就具有可变性,当方法声明返回类型为Stream,我们可以在实现中返回一个FileStream的类 ...
- [C# 基础知识系列]专题四:事件揭秘
转自http://www.cnblogs.com/zhili/archive/2012/10/27/Event.html 引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听 ...
- [C# 基础知识系列]专题四:事件揭秘 (转载)
引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听到“事件”这个概念的,尤其是写UI的时候,当我们点击一个按钮后VS就会自动帮我们生成一些后台的代码,然后我们就只需要在Cl ...
- [C# 基础知识系列]专题八: 深入理解泛型(二)
引言: 本专题主要是承接上一个专题要继续介绍泛型的其他内容,这里就不多说了,就直接进入本专题的内容的. 一.类型推断 在我们写泛型代码的时候经常有大量的"<"和"& ...
- 方法字段[C# 基础知识系列]专题二:委托的本质论
首先声明,我是一个菜鸟.一下文章中出现技术误导情况盖不负责 引言: 上一个专题已和大家分享了我懂得的——C#中为什么须要委托,专题中简略介绍了下委托是什么以及委托简略的应用的,在这个专题中将对委托做进 ...
- [C# 基础知识系列]专题十六:Linq介绍
转自http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html 本专题概要: Linq是什么 使用Linq的好处在哪里 Linq的实际操作例子— ...
- [C# 基础知识系列]专题七: 泛型深入理解(一) (转载)
引言: 在上一个专题中介绍了C#2.0 中引入泛型的原因以及有了泛型后所带来的好处,然而上一专题相当于是介绍了泛型的一些基本知识的,对于泛型的性能为什么会比非泛型的性能高却没有给出理由,所以在这个专题 ...
- [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)
引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...
随机推荐
- 初步接触gulp
首先是安装nodejs,通过nodejs的npm全局安装和项目安装gulp,其次在项目里安装所需要的gulp插件,然后新建gulp的配置文件gulpfile.js并写好配置信息(定义gulp任务),最 ...
- linux安装kibana
下载kibana wget https://artifacts.elastic.co/downloads/kibana/kibana-6.3.2-linux-x86_64.tar.gz -linux- ...
- canal demo搭建全记录
一.环境介绍 canal是阿里开源的中间件,主要用于同步mysql数据库变更.具体参见:https://github.com/alibaba/canal/releases 搭建环境: vmware c ...
- hdu6415 记忆化搜索或找规律
Rikka with Nash Equilibrium Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Sub ...
- springBoot 随笔(一)
服务化的世界,越来越多应用拆分为微服务,有些为了业务而拆,也有为了技术而拆,也有什么都不知道就瞎拆的,反正就是要微服务. 以下为一个认识springBoot的简单过程 1/eclipse 新建 mav ...
- CentOS7系统上的GPSTK源码安装
网址:http://www.gpstk.org/bin/view/Documentation/BuildingGPSTkUnderUnix 这里使用Cmake来安装源码,网站上的原文摘抄如下,有少部分 ...
- day1 登录
#!/usr/bin/env python #Author:windtalker import os, getpass import sqlite3 from time import ctime pr ...
- Java 自增原理
很多人都知道 i++ 和 ++i 的区别 a = i++: a = i; i = i+1; a = ++ i; i = i + 1; a = i; 但碰到 i = i ++;的时候很多人就懵了? i是 ...
- windows搭建redis集群最佳实践
一.redis的下载安装: (1)下载Redis-x64-3.2.100地址:https://github.com/MicrosoftArchive/redis/releases (2)安装后文件如下 ...
- [数]昨天欠下的一道立体几何题HDU-4741
并没有做到这道题,后来听学长说了题意,总之就是立体几何嗯 看了好几份题解,是的我知道是异面线段的距离了,可是看码完全不明orz. 这时候出现了一份清晰易懂甚至给出了公式来源的blog╰(*°▽°*)╯ ...