C#委托事件
Delegate 是在.NET1.0 的时候就已经存在了的特性,因为在准备
总结
初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf
Lambda
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
达式的
时候发现自己对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); public event Notify notifier;
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 的解释是“声明事件:若要在类内声明事件,首先必须声明该事件的委托类型”