登山-C#-再讨论事件,理清事件和委托的关系,理清EventHandler<T>和传统事件的关系

来源:互联网 发布:华晨宇全球歌迷会淘宝 编辑:程序博客网 时间:2024/04/29 12:46

以前在写程序时,总是稀里糊涂的用着委托和事件,但总是不能很清楚的理清出他们之间的关联,只是知道事件是建立在委托的基础上的。

之前也写过一篇关于事件的文章,现在看来太浅了,只是依葫芦画瓢,知道怎么去用而已,而却不知道所以然。其中的一些细节也没有注意到,现在看看是比较肤浅的。

今天再花点时间彻底搞清楚他们之间的关系。

 

在接触事件这个概念时,经常被绕晕,什么delegate,event,EventHandler,Handler之类一堆词。

常常有这样的疑惑,都说事件从委托来,那怎么用的时候没有看到delegate声明委托啊,直接就是EventHandler了

这就涉及到一个概念的理解了

在C#中内置了一个EventHandler<T>范型

他的真面目其实是这样的

public delegate voidEventHandler<T>(object sender, T e)

其实他就是声明了一个委托。

 

我们不用EventHandler<T>范型也是可以构建事件的。

编程中经常遇到的场景是FormA调用FormB,然后从FormB返回一些值给FormA,供其使用。今天就使用这个场景做说明。

先看单纯使用委托完成的事件

首先自定义一个类用户信息的载体

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EventDemo{    /// <summary>    /// 定义CustomerEventArgs,作为消息发布者和消息订阅者之间传递消息的媒介    /// 这里是传递的string类型,也可以替换为其他的类    /// </summary>    public class CustomerEventArgs:EventArgs    {        private string msg;        public CustomerEventArgs(string s)        {            msg = s;        }        /// <summary>        /// Message暴露给外界使用        /// </summary>        public string Message        {            get { return msg; }            set { Message = msg; }        }    }}

接下来定义一个消息的发布者,也就是FormB代表的需要信息的一方

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace EventDemo{    public partial class OldEventPubliser : Form    {        public delegate void CustomerEventHandler(object sender, CustomerEventArgs e);        //这里event的意义在于,如果加了event,外面的类不能通过OldEventPubliser的对象直接调用RaisingMessage        //event关键字,限定了外界对委托变量只能使用+=或-=操作符,对于其他的比如赋值或者调用都会被视为错误        public event CustomerEventHandler RaisingMessage;        public OldEventPubliser()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            if (RaisingMessage != null)            {                CustomerEventArgs ce = new CustomerEventArgs(this.textBox1.Text);                RaisingMessage(sender, ce);                this.Close();            }        }    }}
再定义消息的订阅者,也就是FormA代表的一方

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace EventDemo{    //演示旧的事件的使用方式,OldEventSubscriber是事件订阅者身份    public partial class OldEventSubscriber : Form    {        public OldEventSubscriber()        {            InitializeComponent();        }        /// <summary>        /// 当发布者执行了发布消息动作之后,就会执行到此处,处理接收到消息的地方        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void WhenIGetMessage(object sender, CustomerEventArgs e)        {            this.textBox1.Text = e.Message;        }        private void button1_Click(object sender, EventArgs e)        {            OldEventPubliser publiser = new OldEventPubliser();            //订阅了消息            publiser.RaisingMessage += WhenIGetMessage;            publiser.ShowDialog();        }    }}
在这里我们就没有使用EventHandler<T>范型,同样完成了任务,在这个基础上再去理解EventHandler<T>完成的事件就很容易了。

这里我们还顺道解释了一下event关键字在其中起到的作用,这也是容易困扰人去理解事件的地方。


0 0