大致来说, 委托是一个类, 该类内部维护着一个字段, 指向一个方法. 事件可以被看作一个委托类型的变量, 通过事件注册, 取消多个委托或方法. 本篇分别通过委托和事件执行多个方法, 从中体会两者的区别.
□ 通过委托执行方法
- class Program {
- static void Main(string[] args)
- {
- Example example = new Example();
- example.Go(); Console.ReadKey();
- }
- }
- public class Example
- {
- public delegate void DoSth(string str);
- internal void Go() {
- // 声明一个委托变量, 并把已知方法作为其构造函数的参数
- DoSth d = new DoSth(Print);
- string str = "Hello,World";
- // 通过委托的静态方法 Invoke 触发委托
- d.Invoke(str);
- }
- void Print(string str)
- {
- Console.WriteLine(str);
- }
- }
以上,
○ 在 CLR 运行时, 委托 DoSth 实际上就一个类, 该类有一个参数类型为方法的构造函数, 并且提供了一个 Invoke 实例方法, 用来触发委托的执行.
○ 委托 DoSth 定义了方法的参数和返回类型
○ 通过委托 DoSth 的构造函数, 可以把符合定义的方法赋值给委托
○ 调用委托的实例方法 Invoke 执行了方法
但, 实际上让委托执行方法还有另外一种方式, 那就是: 委托变量(参数列表)
- public class Example
- {
- public delegate void DoSth(object sender, EventArgs e);
- internal void Go() {
- // 声明一个委托变量, 并把已知方法作为其构造函数的参数
- DoSth d = new DoSth(Print);
- object sender = 10;
- EventArgs e = new EventArgs();
- d(sender, e);
- }
- void Print(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- }
以上,
○ 委托 DoSth 的参数列表和方法 Print 的参数列表还是保持一致
○ 委托 DoSth 中的参数 object sender 通常用来表示动作的发起者, EventArgs e 用来表示动作所带的参数.
而实际上, 委托变量(参数列表), 事件就是采用这种形式执行方法的.
□ 通过事件执行方法
- public class Example
- {
- public delegate void DoSth(object sender, EventArgs e);
- public event DoSth myDoSth;
- internal void Go() {
- // 声明一个委托变量, 并把已知方法作为其构造函数的参数
- DoSth d = new DoSth(Print);
- object sender = 10;
- EventArgs e = new EventArgs();
- myDoSth += new DoSth(d);
- myDoSth(sender, e);
- }
- void Print(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- }
以上,
○ 声明了事件 myDoSth, 事件的类型是 DoSth 这个委托
○ 通过 += 为事件注册委托
○ 通过 DoSth 委托的构造函数为事件注册委托实例
○ 采用委托变量 (参数列表) 这种形式, 让事件执行方法
而且, 通过 += 还可以为事件注册多个委托.
- public class Example
- {
- public delegate void DoSth(object sender, EventArgs e);
- public event DoSth myDoSth;
- internal void Go() {
- // 声明一个委托变量, 并把已知方法作为其构造函数的参数
- DoSth d = new DoSth(Print);
- DoSth d1 = new DoSth(Say);
- object sender = 10;
- EventArgs e = new EventArgs();
- // 为事件注册多个委托
- myDoSth += new DoSth(d);
- myDoSth += new DoSth(d1);
- myDoSth(sender, e);
- }
- void Print(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- void Say(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- }
以上, 通过 += 为事件注册 1 个或多个委托实例, 实际上, 还可以为事件直接注册方法.
- public class Example
- {
- public delegate void DoSth(object sender, EventArgs e);
- public event DoSth myDoSth;
- internal void Go() {
- object sender = 10;
- EventArgs e = new EventArgs();
- // 为事件注册多个委托
- myDoSth += Print; myDoSth += Say; myDoSth(sender, e);
- }
- void Print(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- void Say(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- }
□ 通过 EventHandler 执行方法
先来看 EventHandler 的源代码.
可见, EventHandler 就是委托. 现在就使用 EventHandler 来执行多个方法.
- public class Example
- {
- public event EventHandler myEvent;
- internal void Go() {
- object sender = 10;
- EventArgs e = new EventArgs();
- // 为事件注册多个委托
- myEvent += Print; myEvent += Say; myEvent(sender, e);
- }
- void Print(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- void Say(object sender, EventArgs e)
- {
- Console.WriteLine(sender);
- }
- }
总结:
○ 委托就是一个类, 也可以实例化, 通过委托的构造函数来把方法赋值给委托实例
○ 触发委托有 2 种方式: 委托实例. Invoke(参数列表), 委托实例(参数列表)
○ 事件可以看作是一个委托类型的变量
○ 通过 += 为事件注册多个委托实例或多个方法
○ 通过 -= 为事件注销多个委托实例或多个方法
○ EventHandler 就是一个委托
来源: http://www.bubuko.com/infodetail-2873642.html