当我们在点击窗口中的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事件背后发生的事情 (转载)的更多相关文章

  1. [C# 基础知识系列]专题一:深入解析委托——C#中为什么要引入委托

    转自http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html 引言: 对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不 ...

  2. [C# 基础知识系列]专题九: 深入理解泛型可变性

    引言: 在C# 2.0中泛型并不支持可变性的(可变性指的就是协变性和逆变性),我们知道在面向对象的继承中就具有可变性,当方法声明返回类型为Stream,我们可以在实现中返回一个FileStream的类 ...

  3. [C# 基础知识系列]专题四:事件揭秘

    转自http://www.cnblogs.com/zhili/archive/2012/10/27/Event.html 引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听 ...

  4. [C# 基础知识系列]专题四:事件揭秘 (转载)

    引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听到“事件”这个概念的,尤其是写UI的时候,当我们点击一个按钮后VS就会自动帮我们生成一些后台的代码,然后我们就只需要在Cl ...

  5. [C# 基础知识系列]专题八: 深入理解泛型(二)

    引言: 本专题主要是承接上一个专题要继续介绍泛型的其他内容,这里就不多说了,就直接进入本专题的内容的. 一.类型推断 在我们写泛型代码的时候经常有大量的"<"和"& ...

  6. 方法字段[C# 基础知识系列]专题二:委托的本质论

    首先声明,我是一个菜鸟.一下文章中出现技术误导情况盖不负责 引言: 上一个专题已和大家分享了我懂得的——C#中为什么须要委托,专题中简略介绍了下委托是什么以及委托简略的应用的,在这个专题中将对委托做进 ...

  7. [C# 基础知识系列]专题十六:Linq介绍

    转自http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html 本专题概要: Linq是什么 使用Linq的好处在哪里 Linq的实际操作例子— ...

  8. [C# 基础知识系列]专题七: 泛型深入理解(一) (转载)

    引言: 在上一个专题中介绍了C#2.0 中引入泛型的原因以及有了泛型后所带来的好处,然而上一专题相当于是介绍了泛型的一些基本知识的,对于泛型的性能为什么会比非泛型的性能高却没有给出理由,所以在这个专题 ...

  9. [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)

    引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...

随机推荐

  1. linux添加本地yum源

    增加一块硬盘 然后格式化成btrfs格式的文件 mkfs.btrfs /dev/sde 永久挂载 echo "/dev/sde /mnt btrfs defaults 0 0" & ...

  2. vue案例todolist备忘录

    项目效果:https://cinderellastory.github.io/todolist/dist/index.html#/ 项目链接:https://github.com/Cinderella ...

  3. Centos7安装Nginx+PHP+MySQL

    之前曾经在服务器上从头到尾搭过一次环境,但那时新手一枚,很多地方搞不定,是前辈帮忙解决的.这次独自一人在服务器上撘环境,感慨上次没有做好相关笔记,所以事后整理一下,下次再搭环境时可以轻车熟路. 一.准 ...

  4. python 两个 list 获取交集,并集,差集的函数

    1. 获取两个 list 的交集 a = [1, 2, 3, 4] b = [1, 2, 5] print(list(set(a).intersection(set(b)))) 2. 获取两个 lis ...

  5. Kubernetes 入门之Kubernetes 的基本概念和术语

    Kubernetes是什么?    他是一个全新的基于容器技术分布式架构领先方案:    他也是一个开放的开发平台:    他也是一个完备的分布式系统支撑平台:   Kubernetes的基本慨念和术 ...

  6. Webpack学习-Loader

    什么是Loader? 继上两篇文章webpack工作原理介绍(上篇.下篇),我们了解到Loader:模块转换器,也就是将模块的内容按照需求装换成新内容,而且每个Loader的职责都是单一,只会完成一种 ...

  7. learning makefile foreach

  8. lr添加md5方法,字符编码转换,urlcode编码化

    1.使得写lr脚本时可调用md5方法,需要进行以下操作: 1)将md5.h文件加载到Extra Files下: 2)在globals.h文件中添加  #include“md5.h” 3).打开md5文 ...

  9. 关于$(function(){})的问题

    在开发过程中遇到了一个问题 , 页面需要一个列表展示 , 为了方便数据的获取和渲染 ,就选择了easy UI的网格来做 , 这个时候问题就出现了 , 那就是网格需要触发的函数不写在$(function ...

  10. eclipse svn不显示提交人、提交时间的问题

    最近eclipse换到最新的mars版本,装了svn插件subversive后,拉下项目后发现都不显示提交人了,以前都不这样的呀,新版不一样了么? 后来网上搜索总算找到方法解决: Window--&g ...