- 浏览: 663711 次
- 性别:
- 来自: 安徽
文章分类
- 全部博客 (252)
- Html/Div+CSS (12)
- Js/Jquery (34)
- Flex (2)
- Ajax (3)
- Java (35)
- C# (15)
- Spring (16)
- Hibernate (13)
- Struts2 (12)
- Struts1 (7)
- DWR (1)
- iBatis/myBatis (9)
- Tag(JSTL、EL) (1)
- Android (44)
- SQL (7)
- SEO (7)
- Exception (3)
- Tool (10)
- Other (3)
- WebService (9)
- Apache (7)
- Ext (0)
- Utils (12)
- thinking in programme (2)
- Hadoop (0)
- ActiveMQ (0)
- HTML5/CSS3 (0)
- WPF (1)
- NodeJs (1)
- 设计模式 (0)
- 程序人生 (1)
- 随笔 (1)
- Linux (1)
- Load Balance (0)
最新评论
-
drinkjava2:
太复杂了而且不通用,利用ThreadLocal可完美解决这一问 ...
JDBC的多条件动态查询 -
u013107014:
multipartRequest.getFiles(" ...
多文件上传 by MultipartFile and Multiple -
liyys:
可惜没讲你mysql数据库的表的设计
iBatis入门 -
Mapple_leave:
效果还是挺不错的,谢谢了。
中文简体与繁体的转换 -
arcpad:
JS禁用浏览器退格键
Delegate 是在.NET1.0 的时候就已经存在了的特性,因为在准备总结Lambda 表达式的时候发现自己对Delegate 还没有深刻的理解,所以打算先对Delegate 进行整理一下。
Delegate 中文译为“委托”,MSDN 中对Delegate 是这样进行解释的“C# 中的委托 类似于C 或C++ 中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内 。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C 或C++ 中的函数指针不同,委托是面向对象、类型安全的,并且是安全的 。”
我们来通过一个Demo 来进行理解:
class Program { static void OtherClassMethod() { Console .WriteLine("Delegate an other class's method" ); } static void Main(string [] args) { var test = new TestDelegate (); test.delegateMethod = new TestDelegate .DelegateMethod (test.NonStaticMethod); test.delegateMethod += new TestDelegate .DelegateMethod (TestDelegate .StaticMethod); test.delegateMethod += Program .OtherClassMethod; test.RunDelegateMethods(); Console .ReadKey(); } } class TestDelegate { // 声明了一个Delegate 类型名为DelegateMethod ,这种Delegate 类型可以搭载返回值为void ,无参函数 public delegate void DelegateMethod (); // 声明了一个Delegate 对象,注意一个是类型,一个是对象 public DelegateMethod delegateMethod; public static void StaticMethod() { Console .WriteLine("Delegate a static method" ); } public void NonStaticMethod() { Console .WriteLine("Delegate a non-static method" ); } public void RunDelegateMethods() { if (delegateMethod != null ) { Console .WriteLine("---------------------" ); delegateMethod.Invoke(); Console .WriteLine("---------------------" ); } } } |
通过:
test.delegateMethod = new TestDelegate .DelegateMethod (test.NonStaticMethod); test.delegateMethod += new TestDelegate .DelegateMethod (TestDelegate .StaticMethod); test.delegateMethod += Program .OtherClassMethod; |
我们可以发现 delegateMethod 搭载了3 个函数(通过+= 增加搭载的函数,也可以通过-= 来去掉Delegate 中的某个函数),而且通过delegateMethod.Invoke() 运行被搭载的函数,这就是Delegate 可以看作为函数指针的原因。而在Java 中没有委托机制,如果向要实现此功能个人感觉只有通过Java 的内部类来实现。
既然C# 中的委托与C++ 中函数指针如此相似,那么我简单整理一下Delegate 与函数指针的区别:
1、 一个delegate 对象一次可以搭载多个方法,而不是一次一个。当我们唤起一个搭载多个方法的delegate ,所有方法以开始被搭载到delegate 对象的顺序依次被唤起;
2、 一个delegate 对象所搭载的方法并不需要属于同一个类别,一个delegate 对象所搭载的所有方法必须具有与声明时相同的原型和形式,然而这些方法可以有static 也可以有non-static ,可以由一个或多个不同类别的成员组成;
3、 一个delegate type 的声明在本质上是创建了一个新的subtype instance ,该 subtype 派生自 .NET library framework 的 abstract base classes Delegate 或 MulticastDelegate ,它们提供一组public methods 用以询访delegate 对象或其搭载的方法(methods ) ,与函数指针不同,委托是面向对象、类型安全并且安全的。
Delegate 的使用场景:
首先先看下面这段代码
class Program { static void Main(string [] args) { var car = new Car (15); new Alerter (car); car.Run(120); Console .ReadKey(); } class Car { public delegate void Notify (int value); private int petrol = 0; public int Petrol { get { return petrol; } set { petrol = value ; if (petrol < 10) // 当petrol 的值小于10 时出发警报 { if (notifier != null ) { notifier.Invoke(Petrol); } } } } public Car(int petrol) { Petrol = petrol; } public void Run(int speed) { int distance = 0; while (Petrol > 0) { Thread .Sleep(500); Petrol--; distance += speed; Console .WriteLine("Car is running... Distance is " + distance.ToString()); } } } class Alerter { public Alerter(Car car) { car.notifier += new Car .Notify (NotEnoughPetrol); } public void NotEnoughPetrol(int value) { Console .ForegroundColor = ConsoleColor .Red; Console .WriteLine("You only have " + value.ToString() + " gallon petrol left!" ); Console .ResetColor(); } } } |
通过上面的代码,你可能会有这样的疑问,为什么不再public in Petrol 中直接调用Alerter.NotEnoughtPetrol 呢?因为Car 模块和Alerter 模块本身是两个独立的子系统,如果直接调用,则程序的耦合性就会增加,这是程序员的大忌。
其实上面的代码是设计模式中的观察者设计模式 的实现,当汽车在运行中汽油量<10 时,就会发出警报,在上面的代码中Delegate 相当于一个存放回调函数的函数指针,使用Delegate ,我们可以非常方便地实现观察者模式。而其实,在需要使用回调函数时,我们都可以考虑使用Delegate 。
下面我再举个例子吧,取生活中一个场景来说,孩子饿了,要哭,爸爸妈妈听到哭声都会赶过来。如果按照常规的编程方法,我们可能要在Child 类里边实现一个方法来通知爸爸和妈妈,假设有一天这家聚会,爷爷奶奶,姥姥姥爷,姑姑婶婶全过来了,那么孩子必须要通知增加的这些人,我们就不得不修改Child 类里的这个方法。而事实上我们可以这样考虑,将对孩子哭这一事件关心的一类人抽象出来,爷爷奶奶,姥姥姥爷,姑姑婶婶都从该类派生,他们有一个公共的代理,只要他们将自己的行为“注册”到这个代理,孩子一哭,所有被注册进去的事件就会形成一个事件的链表然后顺次执行。在这种模式下Child 类和Observer 类的派生类之间的耦合性大大降低了,我们不需要对Child 类的方法进行任何的修改而只需要讲Observer 类的派生类的各个实例对象对“孩子哭”这一事件的响应注册到“孩子哭”中就可以了。
class Program { public delegate void EventHandle (object sender, EventArgs e); class Entry { public static void Main() { Woman woman = new Woman (); Man man = new Man (); Child child = new Child (); child.call += new EventHandle (woman.observer_call); child.call += new EventHandle (man.observer_call); child.observer_call(null , null ); Console .ReadKey(); } } abstract class observer { public event EventHandle call; public void Subto(observer ob) { this .call += new EventHandle (ob.observer_call); } abstract public void observer_call(object sender, EventArgs e); public void Shout() { if (call != null ) { call(this , null ); } } } class Woman : observer { public override void observer_call(object sender, EventArgs e) { Console .WriteLine("Woman : Oh Baby, mom is coming!" ); Shout(); } } class Man : observer { public override void observer_call(object sender, EventArgs e) { Console .WriteLine("Man : Oh Baby, papa is coming!" ); Shout(); } } class Child : observer { public override void observer_call(object sender, EventArgs e) { Console .WriteLine("Child : Where are my parents? I'm hungry!" ); Shout(); } } } |
上面我定义了一个委托,它的作用是将被委托的函数以参数形式“传递”给事件,从而构成一个事件的链表。
说明,委托在编译的时候会编译成类,因为委托是一个类,所以在任何可以声明类的地方都可以声明委托。它定义了方法的类型,使得可以将方法当作另一个方法的参数传递,这种将方法动态的赋给参数的做法,可以避免在程序中大量地使用if else(switch) 语句,同时使得程序具有更好的扩展性;
在上面的“ public event Notify notifier; ”可以改写为“ public Notify notifier; ”这就是我下面需要整理的Delegate 与Event ;
Delegate 与Event :
通过项目发现很多时候Delegate 与Event 这两个关键字经常会在一起使用,那两者之间是什么关系呢?通过msdn 的解释是“声明事件:若要在类内声明事件,首先必须声明该事件的委托类型”
发表评论
-
C# 可选参数和命名参数
2013-09-05 22:39 1092不说废话,直接上代码 using Syste ... -
C#中JSON序列化和反序列化
2012-12-13 09:33 2645在做项目中使用EF时,发现DataContractJsonSe ... -
Android中http请求(C# MVC接收)
2012-11-28 08:54 4076Android 开发中很多涉及网络通信,因为项目中 ... -
Could not load file or assembly 'System.Data.SQLite' or one of its dependencies.
2012-08-10 09:43 143164位系统上发布net项目报: Could not load ... -
VS2008未能正确加载包visla Studio HTM Editor Package 问题的解决
2012-08-02 23:59 1999因为项目需要在原有 VS2010 的基础上又安装了 ... -
.Net MVC项目部署遇404问题
2012-07-26 00:47 2485MVC1 项目部署成功后,点击链接,会提示 ... -
DebuggerStepThrough 属性
2012-02-10 21:45 1376有时在使用F11进行调试时,经常会进入到一些不想进入的prop ... -
C#中部分类的使用(partial)
2012-02-11 22:18 2161今天工作中遇到了C# ... -
关于Repository模式
2012-02-06 21:49 5101Repository模式: 网上说Repository ... -
MVC2.0前置
2012-02-06 21:48 3558.NET MVC执行过程: 1、 ... -
public void Delete<T>(List<T> EntityList) where T : class, new()
2012-02-02 23:36 2716今天熟悉项目时遇到下面这段代码竟不知道什么意思,记录一下: ... -
C#3.0新特性
2011-12-29 18:37 1185C#3.0 的新特性主要有: ... -
方法参数关键字params、ref及out
2011-12-29 15:05 1089这是三个关键字通过字 ... -
Int?与Int??
2011-12-21 13:11 1280Int?与Int??: Int?:为泛型Nullable< ...
相关推荐
c#委托事件异步例子,委托,异步委托,事件
委托事件,各种的C#的委托事件的常用实例,给初学者和进阶者都能带来不小的好处。
C#委托事件C#委托事件C#委托事件C#委托事件C#委托事件C#委托事件
C#委托事件的学习文档加实例代码,绝对可正常运行,对入门阶段的人群有一定提升能力的作用!
C# 委托和事件 (完整版) C#委托事件 由浅入深,随堂笔记,包你学会_花了不少时间整理,希望大小伙珍惜这来之不易的资源
ASP.Net官网资料 最生动的C# 委托 事件精讲
计算机课程设计C#委托事件
这是C# 委托与事件简单的使用例子。 只是为了初学者更好的接受委托与事件使用方法而已。 程序有两个窗体,一个是主窗体,一个是副窗体。 打开主窗体,在主窗体中点按钮后,打开副窗体,在副窗体中,可以调整主窗体...
C#委托事件详解.................
委托 线程 事件 非常好的说明事例!!
基于c#程序对c语言中的委托事件进行详细的分析与讲解
C#,事件,委托,订阅-发布
学习C#毕竟之路,对事件编程,入门级介绍,全面而且细致
C#委托事件与回调Demo,在不同线程操作时,当想要线程A的任务执行完成后,给线程B反馈时。此方法可以实现这个需求。
这本资料给我们提供了一个很好的例子,水浒烧水的案例,相信会对大家有用,所以就贡献出来于大家分享!
C# 讲解委托和事件的好文章集合。 包括: C# 委托妙文 C# 委托和事件 C# 委托使用方法 C# WndProc的使用方法 文档内有详细代码,您一定可以用它学会委托和事件!
委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件。对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件...
C#委托 C#委托 C#委托C#委托 C#委托
关于C#中委托事件的专门讲解.............................................................................