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

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

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

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

 

在接触事件这个概念时,经常被绕晕,什么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关键字在其中起到的作用,这也是容易困扰人去理解事件的地方。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章