c#中的事件

之前的博客讲到委托,委托本质上是将方法作为方法的参数传给方法。实际开发中,实现某个功能的的代码通常会封装成一个类,本例中字符串处理封装成MyStringProc类,
代码如下:
 1 namespace DelegateTest
 2 {
 3     public delegate string MyStringProcDelegate(string str);
 4     class MyStringProc
 5     {
 6         public string ProcString(string str,MyStringProcDelegate strProcDelegate)
 7         {
 8             return strProcDelegate(str);
 9         }
10     }
11 }
View Code

在调用的时候实例化这个类,再调用对应的方法。如下:

 1 namespace DelegateTest
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             MyStringProc msp = new MyStringProc();
 8             string str1=msp.ProcString("I am good.", StringToLower);
 9             string str2 = msp.ProcString("I am good too", StringToUpper);
10             Console.WriteLine("{0},{1}",str1,str2);
11             Console.ReadKey();
12         }
13         static string StringToLower(string str)
14         {
15             return str.ToLower();
16         }
17         static string StringToUpper(string str)
18         {
19             return str.ToUpper();
20         }
21     }
22 }
View Code
输出如下:
 
现在如果要实现某个功能,这个功能包含多种类型但操作参数都相同,只是内部逻辑不同,而且要依次调用其中几个,这时我们可以只定义一个委托变量,将这些操作的方法依次绑定到这个委托变量即可。
下面是处理一个字符串:字符串前后加'[]',前后后加'{}',代码如下:
 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             MyStringProc msp = new MyStringProc();
 6             MyStringProcDelegate strProcDelegate;
 7             strProcDelegate = StringProc1;
 8             strProcDelegate += StringProc2;
 9             msp.ProcString("I am a good boy",strProcDelegate);
10             Console.ReadKey();
11         }
12 
13         static string StringProc1(string str)
14         {
15             str= "["+str+"]";
16             Console.WriteLine(str);
17             return str;
18         }
19         static string StringProc2(string str)
20         {
21             str= "{" + str + "}";
22             Console.WriteLine(str);
23             return str;
24         }
25     }
View Code

输出如下:

以上并没有达到完全封装,本例用到的MyStringProcDelegate类型的委托变量是可以封装在MyStringProc类中,客户端直接调用该类的方法即可,无需再声明委托变量。如下:

 1 public delegate string MyStringProcDelegate(string str);
 2     class MyStringProc
 3     {
 4         public MyStringProcDelegate strProcDelegate;
 5         public string ProcString(string str)
 6         {
 7             if (strProcDelegate!=null)
 8                 str=strProcDelegate(str);
 9             return str;
10         }
11     }
View Code

调用代码如下:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             MyStringProc msp = new MyStringProc();
 6             msp.strProcDelegate = StringProc1;
 7             msp.strProcDelegate += StringProc2;
 8             msp.ProcString("I am a good boy");
 9             Console.ReadKey();
10         }
11         static string StringProc1(string str)
12         {
13             str= "["+str+"]";
14             Console.WriteLine(str);
15             return str;
16         }
17         static string StringProc2(string str)
18         {
19             str= "{" + str + "}";
20             Console.WriteLine(str);
21             return str;
22         }
23     }
View Code

输出如下:

 
事件
上面的改进无需再客户端声明委托变量,直接调用功能类的方法即可,但是委托变量声明成了public类型,意思就是说客户端可以随意操作该委托变量,破环了面向对象中的封装性。
假如我们将委托变量进行封装,类似于对字段的封装成属性,在c#中event就是对委托类型变量的一种封装,加上event关键字实际上是将普通的委托封装成具有Add和Remove方法
的一种特殊的委托,后面我用reflector反编译工具查看。
 
代码修改如下:
 1 public delegate string MyStringProcDelegate(string str);
 2     class MyStringProc
 3     {
 4         public event MyStringProcDelegate strProcDelegate;
 5         public string ProcString(string str)
 6         {
 7             if (strProcDelegate != null)
 8                 str = strProcDelegate(str);
 9             return str;
10         }
11     }
View Code

调用方法如下:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             MyStringProc msp = new MyStringProc();
 6             msp.strProcDelegate += StringProc1;
 7             msp.strProcDelegate += StringProc2;
 8             msp.ProcString("I am a good boy");
 9             Console.ReadKey();
10         }
11         static string StringProc1(string str)
12         {
13             str= "["+str+"]";
14             Console.WriteLine(str);
15             return str;
16         }
17         static string StringProc2(string str)
18         {
19             str= "{" + str + "}";
20             Console.WriteLine(str);
21             return str;
22         }
23     }
View Code

输出如下:

这样做的好处是,限定了委托的使用,可防止已注册该事件的方法被非法调用。注:事件只能用+=或-=。
下面是对定义的strProcDelegate 变量反编译结果,从中可看出我们在类中定义的该委托变量最终会编译成add、remove两个方法,add为对委托注册方法,remove为对委托取消注册方法。
 
而且虽然strProcDelegate 变量声明称public,但最终会编译成private,如下:
 
MyStringProcDelegate委托类型最终编译如下:
原文地址:https://www.cnblogs.com/kungge/p/4713627.html