zoukankan      html  css  js  c++  java
  • 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委托类型最终编译如下:
  • 相关阅读:
    WF4.0 Beta1 自定义跟踪
    WF4.0 Beta1 流程设计器与Activity Designer
    新版本工作流平台的 (二) 权限算法(组织结构部分)
    WF4.0 Beta1 WorkflowInvoker
    WF4.0 基础篇 (十) Collection 集合操作
    WF4.0 基础篇 (十五) TransactionScope 事物容器
    WF4.0 基础篇 (六) 数据的传递 Arguments 参数
    WF4B1 的Procedural Activity 之InvokeMethod , InvokeMethod<T> 使用
    WF4.0 Beta1 异常处理
    WF4.0 Beta1 变量 Variables
  • 原文地址:https://www.cnblogs.com/kungge/p/4713627.html
Copyright © 2011-2022 走看看