C#学习之事件

.NET的事件模型是建立在委托的机制上,事件机制可以做到,原生的委托也都可以做到;可以说,事件只是对委托的封装,使得用起来更安全。

在具体的代码里,定义一个委托和定义一个事件的差别仅仅是:定义事件时要前面加一个 event 关键字!

正因为这个关键字,编译器就会为这个被封装了的委托暗地里做很多事情,如原生委托可以直接用new来初始化,可以在委托链绑定了很多方法的时候直接用一个 = 操作符来把那些方法清空,等等,而对于事件,编译器把这些都封装了,不能乱来,编译器只是提供了两个方法:add_myEvent、remove_myEvent 让事件客户端仅能通过 += 、 -= 来添加、移除事件的订阅者,如果没有订阅者(也就是委托链为空)时触发事件,那什么也不会发生,等等

一切尽在代码,不废话了

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.IO;
 6 using System.Threading;
 7 
 8 
 9 namespace test
10 {
11 
12     //定义消息类
13     class CalculateEventAgrs:EventArgs
14     {
15         public readonly int x, y;
16         public CalculateEventAgrs(int x, int y)
17         {
18             this.x = x;
19             this.y = y;
20         }
21     }
22 
23 
24     //定义事件发布类
25     class Calculator
26     {
27         //定义一个代理类,声明事件委托
28         public delegate void CalculateEventHandler(object sender, CalculateEventAgrs e);
29 
30         //定义事件成员,代理类类型,提供外部绑定
31         public event CalculateEventHandler MyCalculate;
32 
33         //提供受保护的虚方法,可以由子类覆写来拒绝监视
34         protected virtual void OnCalculate(CalculateEventAgrs e)
35         {
36             //如果没有订阅者,什么都不做
37             if (MyCalculate != null)
38             {
39                 //触发事件
40                 MyCalculate(this, e);
41             }
42         }
43 
44 
45         //触发事件方法,也就是事件发生,可以理解为点击一下鼠标等事件
46         public void Calculate(int x, int y)
47         {
48             //生成事件发生时的消息
49             CalculateEventAgrs e = new CalculateEventAgrs(x,y);
50 
51             //通知所有的 事件的注册者
52             OnCalculate( e);
53         }
54         
55     }
56 
57 
58     //定义事件接收类/事件订阅者/
59     class CalculatorManager
60     {
61         //事件处理函数,可以更改所在类(也就是事件订阅者)的一些属性等
62         public void Add(object sender, CalculateEventAgrs e)
63         {
64             Console.WriteLine(e.x + e.y);
65         }
66 
67         //事件处理函数
68         public void Subtract(object sender, CalculateEventAgrs e)
69         {
70             Console.WriteLine(e.x - e.y);
71         }
72     }
73 
74 
75     class Program
76     {   
77         static void Main(string[] args)
78         {
79             Calculator calculate = new Calculator();//事件发布者
80 
81             CalculatorManager cm = new CalculatorManager();//事件订阅者/接收者
82 
83           //  calculate.MyCalculate = new Calculator.CalculateEventHandler();
84 
85 
86             calculate.MyCalculate += cm.Add;//订阅事件:cm 这个对象主动去订阅 calculate对象里的MyCalculate事件
87 
88             calculate.MyCalculate -= cm.Subtract;//取消订阅:如果委托链里没有这个事件,也不会抛出异常,什么也不做
89 
90             calculate.Calculate(100,200);//事件发生
91 
92             Console.ReadKey();
93         }
94 
95     }
96 }

在83行那里,如果去掉注释再编译的话,会提示错误如下:

如果用到:calculate.MyCalculate = cm.Add; 这句代码的话也会提示一样的错误。

原文地址:https://www.cnblogs.com/zouzf/p/2673638.html