登山-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關鍵字在其中起到的作用,這也是容易困擾人去理解事件的地方。


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