假如有一个场景:A类的某个动作/事件,触发了B类的某个响应,一开始可能会想到委托事件:
1.先声明委托
2.再声明事件
3.订阅:A的事件连接B的响应
4.结果:A类的事件触发了,B类的响应也随之触发
(一、普通做法)
1.首先定义一个A类,声明委托、事件
public class Teacher
{
//官方定义:委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
//个人通俗点的理解:就是长某某样子的函数,如长得类似与"void DeleAct(string name)"--没有返回值带一个参数的函数
public delegate void DeleAct(string name);
public event DeleAct ActHandler;
public void Come()
{
Console.WriteLine("老师来了");
if (ActHandler != null)
ActHandler("杨老师");
}
}
2.再定义一个响应B类
public class Students
{
public void Action_Teacher(string name)
{
Console.WriteLine("全班起立,喊:{0}好", name);
}
}
3.然后Main函数里订阅事件,连接两个关联动作
Teacher teacher = new Teacher();
Students student = new Students();
teacher.ActHandler += student.Action_Teacher;
4.再触发A类的动作
Console.WriteLine("订阅好之后,开始触发动作了");
teacher.Come();//Come会触发Students的Action_Teacher
Console.Read();
结果:
订阅好之后,开始触发动作了
老师来了
全班起立,喊:杨老师好
(二、用EventHandler改造)
如果又有一个校长Headmaster类,希望传递更多信息给Students类,比如姓名、获奖数、年龄等呢
或者有另一个青年教师YoungTeacher类,也希望传递更多信息给Students类,比如爱好、毕业院校等呢?
那就要定义多个委托,定义不同的参数类
此时EventHandler就派上用场了,使用它:
(1).不必定义多个不同名字不同类型的委托
(2)搭配EventArgs,可传递多个信息
过程:
1.定义一个参数类HeadArgs,用来传递校长的信息。
注意:必须继承于EventArgs的类,定义时可以包含定义很多字段属性,包含很多信息。
public class HeadArgs : EventArgs
{
public string Name { get; set; }
public int MedalCount { get; set; }
}
2.直接声明EventHandler事件,省了声明委托这一步,并且调用时,必须用两个参数(object sender, EventArgs e)。
如ActHandler(null, args),其中args是继承于EventArgs 的HeadArgs。
public class Headmaster
{
public event EventHandler ActHandler;
public void Come()
{
Console.WriteLine("校长来了");
HeadArgs args = new HeadArgs() { Name = "王校长", MedalCount = 10 };
ActHandler(null, args);
}
}
3.B类的响应事件写一个带object sender, EventArgs e参数的方法
public class Students
{
public void Action_Master(object sender, EventArgs e)
{
HeadArgs args = e as HeadArgs;
Console.WriteLine("全班起立,喊:{0}好", args.Name);
Console.WriteLine("校长的获奖数是:{0}", args.MedalCount);
}
}
4.连接两个关联动作
Students student = new Students();
Headmaster master = new Headmaster();
master.ActHandler += student.Action_Master;
5.触发事件
Console.WriteLine("-----------------------");
master.Come();//触发Students的Action_Master
Console.Read();
结果:
-----------------------
校长来了
全班起立,喊:王校长好
校长的获奖数是:10
(三、用EventHandler<T>改造,简约)
假如王校长只有一个name要传递呢,那就可以使用EventHandler<T>使整个过程更简单。改造如下:
1.定义一个校长类,此处EventHandler<T>中T的类型为string,这样就省略了一个HeadArgs参数类,因为没那么多信息要传递。
public class Headmaster
{
public event EventHandler<string> ActHandler;
public void Come()
{
Console.WriteLine("校长来了");
ActHandler(null, "王校长");//只传递"王校长"这个string即可
}
}
2.Stendent类中,方法的参数为object和string类型
public class Students
{
public void Action_Master(object sender, string name)
{
Console.WriteLine("全班起立,喊:{0}好", name);
}
}
3.订阅连接
Students student = new Students();
Headmaster master = new Headmaster();
master.ActHandler += student.Action_Master;
4.输出:
Console.WriteLine("-----------------------");
master.Come();//触发事件
Console.Read();
结果:
-----------------------
校长来了
全班起立,喊:王校长好
总结:使用EventHandler
(1).标准化,代码美观统一;
(2)可省略定义委托这一步。不必定义多个不同类型的委托;
(2)搭配EventArgs,可传递多个信息。