以前在寫程序時,總是稀裏糊塗的用着委託和事件,但總是不能很清楚的理清出他們之間的關聯,只是知道事件是建立在委託的基礎上的。
之前也寫過一篇關於事件的文章,現在看來太淺了,只是依葫蘆畫瓢,知道怎麼去用而已,而卻不知道所以然。其中的一些細節也沒有注意到,現在看看是比較膚淺的。
今天再花點時間徹底搞清楚他們之間的關係。
在接觸事件這個概念時,經常被繞暈,什麼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關鍵字在其中起到的作用,這也是容易困擾人去理解事件的地方。