1. 程式人生 > >C# 標準事件模式

C# 標準事件模式

bject 返回值 不必要 virt void ret last AS str

.NET框架為事件定義了一個標準模式,它的目的是保持框架和用戶代碼之間的一致性。

標準事件的模式核心是SystemEventArgs——預定義的沒有成員的框架類(不同於靜態Empty屬性)

EventArgs表示包含事件數據的類的基類,並提供用於不包含事件數據的事件的值。用於為事件傳遞信息的基類。

在下面例子中,我們定義EventArgs的子類,用於事件PriceChanged被引發時,傳遞新舊Price值:

    public class PriceChangedEventArgs : EventArgs
    {
        public readonly decimal LastPrice;
        
public readonly decimal NewPrice; public PriceChangedEventArgs(decimal lastPrice, decimal newPrice) { LastPrice=lastPrice; NewPrice= newPrice; } }

考慮到復用性,EventArgs子類根據它包含的內容命名(而非根據將被使用的事件命名)。

選擇或定義事件的委托,需遵循三條原則:

  • 委托必須以void作為返回值
  • 委托必須接受兩個參數:第一個是object類,第二個是EventArgs的子類。
  • 委托的名稱必須以EventHandler結尾

完整例子:

class Test 
        public static void Main()
        {
            InitializeComponent();
            Stock stock = new Stock("THPW");
            stock.Price = 27.10M;
            //註冊PriceChanged事件
            stock.PriceChanged += stock_PriceChanged;
            stock.Price 
= 31.59M; } static void stock_PriceChanged(object sender, PriceChangedEventArgs e) { if ((e.NewPrice - e.LastPrice) / e.LastPrice > 0.1M) { Console.WriteLine("Alert,10% stock increase!"); } } } public class Stock { string symbol; decimal price; public Stock(string symbol) { this.symbol = symbol; }
//定義委托事件
public event EventHandler<PriceChangedEventArgs> PriceChanged;
protected virtual void OnPriceChanged(PriceChangedEventArgs e) { if (PriceChanged != null) PriceChanged(this, e); } public decimal Price { get { return price; } set { if (price == value) return;
            price = value;
          OnPriceChanged(new PriceChangedEventArgs(price, value));
                
            }
        }
    }

    public class PriceChangedEventArgs : EventArgs
    {
        public readonly decimal LastPrice;
        public readonly decimal NewPrice;

        public PriceChangedEventArgs(decimal lastPrice, decimal newPrice)
        {
            LastPrice=lastPrice;
            NewPrice= newPrice;
        }
    }    

如果事件不傳遞額外的信息,可以使用預定義的非泛化委托EventHandler。如下所示:

    class Test
    {
        public static void Main()
        {
            InitializeComponent();
            Stock stock = new Stock();
            stock.Price = 27.10M;
            //註冊PriceChanged事件
            stock.PriceChanged += stock_PriceChanged;
            stock.Price = 31.59M;
        }

        static void stock_PriceChanged(object sender, EventArgs e)
        {
           Console.WriteLine("價格變換了!");
        }
    }

    public class Stock
    {
        decimal price;

        public event EventHandler PriceChanged;

        protected virtual void OnPriceChanged(EventArgs e)
        {
            if (PriceChanged != null) PriceChanged(this, e);
        }

        public decimal Price
        {
            get { return price; }
            set
            {
                if (price == value) return;
                price = value;

                //OnPriceChanged(new EventArgs());

                OnPriceChanged(EventArgs.Empty);
            }
        }
    }

註意:

上面例子中事件除了傳遞已發生信息,沒有傳遞其他信息。

你可以使用 OnPriceChanged(new EventArgs()) 來完成事件的傳遞。

為了避免對EventArgs不必要的初始化,建議使用EventArgs.Empty屬性。使用這樣一個“空的”靜態引用的對象,避免多余地去創建一個新對象。

微軟的大部分控件所拋出的事件都有兩個參數,第一個是 object 類型的,第二個是 EventArgs 類型的。

技術分享圖片

你從EventArgs e那裏得不到任何此次事件相關需要傳遞的信息,真正傳遞的信息都在sender中。

C# 標準事件模式