C#複習筆記-事件

使用委託時,一般會出現兩種角色,廣播者和訂閱者。廣播者是包含委託字段的類型,它通過委託決定何時進行廣播。訂閱者是發發的接收者。它通過廣播者的委託上調用+=或者-=來決定何時開始監聽何時結束監聽。事件是一種使用委託的功能實現廣播者或訂閱者模型的結構。使用委託的主要目的是保證訂閱者之間互不影響。聲明時間的最簡單的方法是在委託成員前面加上event關鍵字:

//定義一個委託,接受2個decimal類型的參數
    public delegate void PirceChangedHandler(decimal oldPirce, decimal newPrice);

    public class Broadcaster
    {
        //定一個PirceChanged事件
        public event PirceChangedHandler PriceChanged;
        decimal _price;

        public decimal Price
        {
            get { return _price; }
            set
            {
                if (_price == value)
                    return;
                decimal oldprice = _price;
                _price = value;
                if (PriceChanged != null)
                    PriceChanged(oldprice, _price);
            }
        }
    }

EventArgs是爲事件傳遞信息的基類。我們可以繼承EventArgs以便於在事件觸發的時候傳遞值參數。EventArgs子類應當根據它包含的信息來命名,二維根據使用它的時間命名。一般將數據以屬性或制度字段的方式暴露給外界。

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

定義了EvaenArgs子類以後,下一步就要定義事件的委託了,委託必須滿足下面三個條件:

  • 委託必須以void作爲返回值。
  • 委託必須接受兩個參數。第一個參數是object類型,第二個參數是EventArgs子類。第一個參數表明了時間的廣播者,第二個參數包含了需要傳遞的信息。
  • 委託的名稱必須以EventHandler結尾。
public delegate void PriceChangedEventHandler(object sender, PriceChangedEventArgs e);

框架定義了一個名爲System.EventHandler<>的泛型委託也滿足以上三個條件:

    public class Stock
    {
        public event EventHandler<PriceChangedEventArgs> PriceChanged;
        protected virtual void OnPriceChanged(PriceChangedEventArgs e)
        {
            var temp = PriceChanged;//爲了多線程下可靠的工作,在測試和調用委託之前需要將他保存到零時變量
            if (temp != null)
                temp(this, e);
            PriceChanged?.Invoke(this, e);//也可以這麼寫,線程安全又書寫簡單,是最好的觸發方式。
        }
    }

  完整的代碼如下:

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

        public PriceChangedEventArgs(decimal lastPrice, decimal newPrice)
        {
            LastPrice = lastPrice;
            NewPrice = newPrice;
        }
    }
    public class Stock
    {
        public event EventHandler<PriceChangedEventArgs> PriceChanged;
        protected virtual void OnPriceChanged(PriceChangedEventArgs e)
        {
            //爲了多線程下可靠的工作,調用委託之前需要將他保存到零時變量
            //var temp = PriceChanged;
            //if (temp != null)
            //    temp(this, e);
            PriceChanged?.Invoke(this, e);//也可以這麼寫,線程安全又書寫簡單,是最好的觸發方式。
        }

        decimal price;
        public decimal Price
        {
            get { return price; }
            set
            {
                if (price == value)
                    return;
                decimal priceold = price;
                price = value;
                OnPriceChanged(new PriceChangedEventArgs(priceold, price));
            }
        }
    }

using App;

Stock stock = new Stock();
stock.Price = 20;
stock.PriceChanged += Stock_PriceChanged;

for (int i = 0; i < 10; i++)
{
    stock.Price = i + 20;
    Task.Delay(1000).Wait();
}

void Stock_PriceChanged(object? sender, PriceChangedEventArgs e)
{
    Console.WriteLine($"當前價格:{e.NewPrice},上一次的價格{e.LastPrice}");
}
Console.ReadKey();

 

和方法一樣,事件也可以重寫,可以是虛的,抽象的密封的,靜態的。

 

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