MiCoos 哟,写bug呢?

C#基础 事件

2019-09-05
GHMicoos

概述:事件。

零 多播委托

1.定义与使用

  • 定义:一个委托变量可以引用一系列的委托,在这一系列委托中,每个委托都顺序只想一个后续的委托,从而形成了一个委托链。调用该委托变量时,会按照顺序(顺序不可预测)连续调用多个方法。
  • 可以使用+=-=操作符来向委托中添加或者删除方法。(委托重载了这两个操作符)(其实这两个方法是Delegate中的静态方法CombineRemove。)
  • 如果-=之后,委托中不存在方法了,那么该委托变量是null。
  • 使用GetInvocationList方法可以获取一个委托数组,数组包含了添加到委托的方法(可能多个)。

MyAction action ;
action = () => Console.WriteLine("1");
action += () => Console.WriteLine("2");

//输出 1 2
action();

action -= action.GetInvocationList()[0] as MyAction;
action -= action.GetInvocationList()[0] as MyAction;
//下句代码会报错,因为action中的方法移除完了之后,action是null
//action();

2.多播委托的注意

  • 如果多播委托中的方法有返回值,那么只能返回最后一个方法的返回结果。

public static int Method01() => 1;
public static int Method02() => 2;

//测试代码    
MyAction action ;
action = Method01;
action += Method02;
//r得到的是委托中最后一个调用的方法的返回结果
//一般情况会使最后一个添加方法的返回值,因为委托调用方法的顺序是不可好的。
//r==2 (一般情况)
var r = action();

  • 多播委托中的方法调用顺序是不可预测的,避免编写依赖以特定顺序调用方法的代码。
  • 因为调用多播委托时,会调用委托中包含的方法,但是如果其中一个方法抛出异常,那么整个迭代就会停止。
  • 如果使用了=为委托赋值一个方法,那么会清除以前已经添加的方法。

一 多播委托实现发布订阅模式

二 事件

  • 事件基于委托,为委托提供一种发布/订阅机制。
  • 事件的签名public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
  • 事件一般使用带两个参数的方法;其中一个参数是一个对象,包含事件的发送者;第二个参数提供事件的相关信息。

class CarInfoEventArgs : EventArgs
{
    public string Car { get; private set; }
    public CarInfoEventArgs(string car)
        => Car = car;
}

class CarDealer
{
//可以使用下面的 C#的简化写法
//public event EventHandler<CarInfoEventArgs> NewCarInfo;
    private EventHandler<CarInfoEventArgs> _newCarInfo;
    public event EventHandler<CarInfoEventArgs> NewCarInfo
    {
        add { _newCarInfo += value; }
        remove { _newCarInfo -= value; }
    }


    public void NewCar(string car)
    {
        Console.WriteLine($"CarDealer,new car {car}");
        if (_newCarInfo != null)
        {
        _newCarInfo(this, new CarInfoEventArgs(car));
        }
    }
}

class Customer
{
    private string name;
    public Customer(string name)
        => this.name = name;

    public void NewCarIsHere(object sender, CarInfoEventArgs e)
    {
        Console.WriteLine($"{name}:car {e.Car} is new");
    }
}

//测试代码
var dealer = new CarDealer();
//michael对象 订阅 dealer的NewCarInfo方法
var michael = new Customer("Michael");
dealer.NewCarInfo += michael.NewCarIsHere;

var nick = new Customer("Nick");
//nick对象 订阅 dealer的NewCarInfo方法
dealer.NewCarInfo += nick.NewCarIsHere;

//dealer 发布动作,然后会依次调用订阅方法
//输出:
/*
CarDealer,new car 新车马自达
Michael:car 新车马自达 is new
Nick:car 新车马自达 is new
*/
dealer.NewCar("新车马自达");


Similar Posts

下一篇 C#基础 委托

Comments