概述:事件。
零 多播委托
1.定义与使用
- 定义:一个委托变量可以引用一系列的委托,在这一系列委托中,每个委托都顺序只想一个后续的委托,从而形成了一个委托链。调用该委托变量时,会按照顺序(顺序不可预测)连续调用多个方法。
- 可以使用
+=
、-=
操作符来向委托中添加或者删除方法。(委托重载了这两个操作符)(其实这两个方法是Delegate
中的静态方法Combine
、Remove
。) - 如果
-=
之后,委托中不存在方法了,那么该委托变量是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("新车马自达");