標籤:
使用事件定義和發布事件
事件是建立在委託的基礎上的,當某類發生某一事情後,可以通過事件機制通知已經註冊的類或對象正在發生的事情,然後這些類或對象做出響應。
事件的本質是委託,但它通常是特定的函數類型,可以將事件理解為委託變數,訂閱事件就是為委託變數賦值,同樣也是使用“+=”/“-=”。
在定義事件之前要先定義委託,只不過這個委託是特定的函數類型,它沒有傳回值,並且具有兩個參數sender和arg。
例如:
Public delegate void PriceChangedEventHandler(object sender,PriceChangedEventAgrs arg);
為什麼會這樣呢?這是因為在.Net 架構中,事件是基於EventHandler委託和EventArgs基類的。
在看上面的例子中的兩個參數,一個是object類型的sender,表示事件的發起者,一個是PriceChangedEventArgs 類型的arg,表示事件參數,通常是由EventArgs類派生出來的,所以,在定義一個事件之前,通常先定義一個參數類,派生自EventArgs,該類包含了事件發起者需要傳遞給事件訂閱者的全部資訊。
定義好委託之後,需要定義一個事件,可以理解為定義一個委託變數,只不過不是直接定義,需要加上“event”關鍵字,來說明這是一個事件,不過可以理解為就是一個委託變數。
例如:
Public event PricechangedEventHandler PriceChanged;
接下來就是引發事件,可以理解為使用委託變數,引發事件通常放在一個名為OnXXXX()的函數中,這樣在在其他地方調用該函數時,就引發事件,即使用委託變數,調用相應的函數(事件處理常式)。
訂閱和處理事件
訂閱,實際上就是將函數添加到委託變數的函數列表中,在這裡,就是將事件處理常式添加到事件的列表中。
處理事件,就是委託變數調用的函數,即事件發生後呼叫事件處理常式。
例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EventApp
{
class Program
{
/// <summary>
/// 實現使用者訂閱事件,也就是為委託變數賦值,通過+=。。。
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//定義兩個shop對象,用來引發事件
Shop shop1 = new Shop("Shop1");
Shop shop2 = new Shop("Shop2");
//定義兩個customer對象,用來訂閱事件並處理事件
Customer cust1 = new Customer("Customer1");
Customer cust2 = new Customer("Customer2");
//cust1訂閱shop1的pricechanged事件
shop1.PriceChanged += cust1.Shop_PriceChanged;
//引發事件
Console.WriteLine("1. shop1.UpdatePrice(\"Goods1\",2.2f)......");
shop1.UpdatePrice("Goods1", 2.2f);
//cust2訂閱shop2的pricechanged事件
shop2.PriceChanged += cust2.Shop_PriceChanged;
//引發事件
Console.WriteLine("2. shop2.UpdatePrice(\"Goods2\",3.4f),......");
shop2.UpdatePrice("Goods2", 3.4f);
//cust2訂閱shop1的pricechanged事件
shop1.PriceChanged += cust2.Shop_PriceChanged;
//引發事件
Console.WriteLine("3. shop1.UpdatePrice(\"Goods3\",55.2f)......");
shop1.UpdatePrice("Goods3", 55.2f);
//cust1取消shop1的pricechanged事件
shop1.PriceChanged -= cust1.Shop_PriceChanged;
//引發事件
Console.WriteLine("4. shop1.UpdatePrice(\"Goods4\",9.2f)......");
shop1.UpdatePrice("Goods4", 9.2f);
Console.ReadLine();
}
/// <summary>
/// 商品價格變化發生時的事件參數
/// </summary>
public class PriceChangedEventArgs:EventArgs
{
private string str_Name;
public string Str_Name
{
get { return this.str_Name; }
}
private float flo_Price;
public float Flo_Price
{
get { return this.flo_Price; }
}
public PriceChangedEventArgs(string name,float newprice)
{
this.str_Name = name;
this.flo_Price = newprice;
}
}
/// <summary>
/// 定義委託
/// </summary>
/// <param name="sender"></param>
/// <param name="arg"></param>
public delegate void PriceChangedEventHandler(object sender, PriceChangedEventArgs arg);
public class Shop
{
private string shopname;
/// <summary>
/// 屬性
/// </summary>
public string ShopName
{
get { return this.shopname; }
}
/// <summary>
/// 建構函式
/// </summary>
/// <param name="spname"></param>
public Shop(string spname)
{
this.shopname = spname;
}
public event PriceChangedEventHandler PriceChanged; //相當於聲明委託變數,這裡通過event關鍵字將其稱為事件
/// <summary>
/// 引發事件的函數
/// </summary>
/// <param name="arg"></param>
protected void OnPriceChanged(PriceChangedEventArgs arg)
{
if (this.PriceChanged!=null)
{
PriceChanged(this, arg); //相當於使用委託變數,這裡只不過將使用委託變數放在了一個函數裡,整體成為引發事件,實質就是使用委託變數。
}
}
public void UpdatePrice(string nm,float nprice)
{
PriceChangedEventArgs arg = new PriceChangedEventArgs(nm, nprice);
this.OnPriceChanged(arg);
}
}
/// <summary>
/// 客戶資訊,訂閱事件
/// </summary>
public class Customer
{
private string name;
public string _Name
{
get { return this.name; }
}
public Customer(string nm)
{
this.name = nm;
}
/// <summary>
/// PriceChanged事件處理函數
/// </summary>
/// <param name="sender"></param>
/// <param name="arg"></param>
public void Shop_PriceChanged(object sender, PriceChangedEventArgs arg)
{
Shop sp = sender as Shop;
if (sp != null)
{
Console.WriteLine("{0}收到{1}:{2}新價格為{3}¥", this._Name, sp.ShopName, arg.Str_Name, arg.Flo_Price);
}
}
}
}
}
C# 關於事件的一些心得