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

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

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

输出如下:

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

 public delegate string MyStringProcDelegate(string str);
class MyStringProc
{
public MyStringProcDelegate strProcDelegate;
public string ProcString(string str)
{
if (strProcDelegate!=null)
str=strProcDelegate(str);
return str;
}
}

调用代码如下:

 class Program
{
static void Main(string[] args)
{
MyStringProc msp = new MyStringProc();
msp.strProcDelegate = StringProc1;
msp.strProcDelegate += StringProc2;
msp.ProcString("I am a good boy");
Console.ReadKey();
}
static string StringProc1(string str)
{
str= "["+str+"]";
Console.WriteLine(str);
return str;
}
static string StringProc2(string str)
{
str= "{" + str + "}";
Console.WriteLine(str);
return str;
}
}

输出如下:

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

调用方法如下:

 class Program
{
static void Main(string[] args)
{
MyStringProc msp = new MyStringProc();
msp.strProcDelegate += StringProc1;
msp.strProcDelegate += StringProc2;
msp.ProcString("I am a good boy");
Console.ReadKey();
}
static string StringProc1(string str)
{
str= "["+str+"]";
Console.WriteLine(str);
return str;
}
static string StringProc2(string str)
{
str= "{" + str + "}";
Console.WriteLine(str);
return str;
}
}

输出如下:

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

c#中的事件的更多相关文章

  1. C++中的事件分发

    本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...

  2. javascript中的事件冒泡和事件捕获

    1.事件冒泡 IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档).以下面的HTML ...

  3. jQuery文本框中的事件应用

    jQuery文本框中的事件应用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  4. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  5. jQuery中的事件绑定方法

    在jQuery中,事件绑定方法大致有四种:bind(),live(), delegate(),和on(). 那么在工作中应该如何选择呢?首先要了解四种方法的区别和各自的特点. 在了解这些之前,首先要知 ...

  6. 四、jquery中的事件与应用

    当用户浏览页面时,浏览器会对页面代码进行解释或编译--这个过程实质上是通过时间来驱动的,即页面在加载时,执行一个Load事件,在这个事件中实现浏览器编译页面代码的过程.时间无论在页面元素本身还是在元素 ...

  7. ActiveX(二)Js 监听 ActiveX中的事件

    在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...

  8. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  9. jQuery:详解jQuery中的事件(一)

    之前用过一些jQuery的动画和特效,但是用到的部分也不超过10%的样子,感觉好浪费啊——当然浪费的不是jQuery,而是Web资源.后来就想深入研究下jQuery的内部机理,读过两遍jQuery源代 ...

  10. DOM中的事件对象

    三.事件对象事件对象event1.DOM中的事件对象(1).type:获取事件类型(2).target:事件目标(3).stopPropagation() 阻止事件冒泡(4).preventDefau ...

随机推荐

  1. [转]linux14.04下caffe的安装步骤

     linux14.04下caffe的安装步骤   原文地址:http://blog.csdn.net/xiaoyang19910623/article/details/52997481?locatio ...

  2. NSCalenda日历类

    1. //将数据库时间和当前时间相比,得出时间差. + (NSString *)dateDescriptionWithDate:(NSDate *)date{ // NSCalendar日历类,提供了 ...

  3. linux下使用SSL代理(SSLedge)

    refer to: https://eurekavpt.com/page/ssledge-on-linux 启动非常简单./ssledge-term-x64 -f config -D 其中的confi ...

  4. MyEclipse 10 中如何更改字体

    打开Myeclipse软件.window->preferences->General->Appearance->Colors and Fonts然后在窗口的右边会显示一些如下图 ...

  5. hdu 5101 n集合选2个不同集合数使和大于k

    http://acm.hdu.edu.cn/showproblem.php?pid=5101 给n个集合,选择两个来自不同集合的数,加和大于k,问有多少种选择方案. 答案=从所有数中选择的两个加和大于 ...

  6. mongoDB研究笔记:journaling保证意外故障下的数据完整性

    mongoDB的Journaling日志功能与常见的log日志是不一样的,mongoDB也有log日志,它只是简单记录了数据库在服务器上的启动信息.慢查询记录.数据库异常信息.客户端与数据库服务器连接 ...

  7. 从CLR角度来看值类型与引用类型

    前言 本文中大部分示例代码来自于<CLR via C# Edition3>,并在此之上加以总结和简化,文中只是重点介绍几个比较有共性的问题,对一些细节不会做过深入的讲解. 前几天一直忙着翻 ...

  8. SQL Server 事务语法

    事务全部是关于原子性的.原子性的概念是指可以把一些事情当做一个单元来看待.从数据库的角度看,它是指应全部执行或全部都不执行的一条或多条语句的最小组合. 为了理解事务的概念,需要能够定义非常明确的边界. ...

  9. jeesite笔记

    环境 Github上的不能初始化数据库:https://github.com/thinkgem/jeesite 官网上的可以: http://jeesite.com/ 用 Idea 打开,修改 \sr ...

  10. windows下使用批处理脚本实现多个版本的JDK切换

    一.JDK版本切换批处理脚本 我们平时在window上做开发的时候,可能需要同时开发两个甚至多个项目,有时不同的项目对JDK的版本要求有区别,这时候我们可能会在一台电脑上安装多个版本的JDK,如下图所 ...