关于c#中的delegate,经过《用好C#Delegate》介绍,应该牢固建立起以下的概念:
一个delegate type 的声明在本质上是创建了一个新的subtype instance,该subtype 派生自.NETlibrary framework 的abstractbase classes Delegate 或MulticastDelegate,它们提供一组public methods 用以询访delegateobject 或其搭载的方法(methods)。
Delegates are reference types that take a method asparameter and once the delegate is invoked the method is called.
一个delegate object 所搭载的方法(methods)并不需要属于同一个类别。一个delegateobject 所搭载的所有方法(methods)必须具有相同的原型和形式。然而,这些方法(methods)可以即有static 也有non-static,可以由一个或多个不同类别的成员组成。
What the CLR does to C#delegates
Suppose we declare a C# delegate as shown inthe code listing below:
public class DelegareUsage
{
public delegate void MyDelegate(int number);
}
What the CLR does is it creates a class in theIL code as shown in the figure below.
As we can see in the preceding figure asealed class is created in the IL after the compilation of the code. As we cansee the delegate class contains by default three functions: BeginInvoke, EndInvoke, Invoke.
1.理论上,要想使用delegate, 你必须首先实例化一个delegate对象:
MyDelegate del = new MyDelegate(DelegatedFunction);
你也可以简写为:
MyDelegate del = DelegatedFunction; //背后实质上是一样地实例化构造对象
2. Invoke: This is the default way by which a method is beingcalled. And if want to calldelegated method synchronously you should call Invoke(…)
3. BeginInvoke: Calling this function will return control to the caller assoon as the preceding statement is executed and it will not wait for thefunction to return or end the execution.
The hierarchy of the inheritance for thedelegates is that the user defined delegate is derived from a multicastdelegate. Each delegate contains an invocation list, in other words we canattach any number of functions to the delegates. The functions can be attachedto the invocation list using the operator +=. The functions in the multicastdelegates are called in the order they are added.
Event和delegate
Event和delegate有很多的相似之处,并且delegate完全能实现event的功能。相对delegate来说,客户端即观察着只能调用+=或者-=来添加自己对应事件触发的通知,它不能调用new来实例化发布者的event事件如单击事件,或者直接将发布者的event对象直接赋值null从而撤销发布者所有通知列表。观察者不能也不应该有权限实例化事件发布者的消息列表。同理,观察者不应该能控制事件发布者对事件的通知,这些所有的操作应该都是发布者内部的事件而不能交由外部对象来控制。因此,才产生了event对象,它是通过对delegate的限制来封装一部分本来就不应该暴露在外的行为,从而更符合面向对象的思维。Event关键字只不过是CLR给我们所定义的delegate对象的一个封装。
using System;
namespace Delegate_vs_Event
{
class Program
{
public delegate string TestDelegate(string input);
public static TestDelegate myDelegate;
public static event TestDelegate myEvent;
static void Main(string[] args)
{
//在声明委托和事件的类内部,对于Delegate与Event的实例的初始化和调用操作没有任何区别;
//myDelegate = new TestDelegate(TestEvent);
//myEvent = new TestDelegate(TestEvent);
//myDelegate("Delegate");
//myEvent("Event");
Subject subject = new Subject();
Observer ob = new Observer(subject);
subject.Start();
Console.Read();
}
static string TestEvent(string param)
{
Console.WriteLine("Hello " + param);
return string.Empty;
}
}
class Subject
{
public delegate void TestHandleForReg(string param);
public event TestHandleForReg TestHandleEvent;
public TestHandleForReg TestHandleDelegate;
public void Start()
{
//对于Delegate与Event的实例,其订阅(Subscribe,即+=)或取消订阅(Unsubscribe,即-=)的操作没有任何区别;
TestHandleDelegate += Method_Subject1;
TestHandleDelegate += Method_Subject2;
TestHandleDelegate -= Method_Subject2;
TestHandleEvent += Method_Subject1;
TestHandleEvent += Method_Subject2;
TestHandleEvent += Static_Method_Subject;
Console.WriteLine("Call internal method result by [Delegate] ");
TestHandleDelegate("Delegate");
Console.WriteLine();
Console.WriteLine("Call internal method result by [Event] ");
TestHandleEvent("Event");
Console.WriteLine();
}
public void Method_Subject1(string str)
{
Console.WriteLine("Method_Subject1");
}
public void Method_Subject2(string str)
{
Console.WriteLine("Method_Subject2");
}
public static void Static_Method_Subject(string str)
{
Console.WriteLine("Static_Method_Subject");
}
}
class Observer
{
public Observer(Subject subject)
{
subject.TestHandleEvent += Method_Observer;
subject.TestHandleDelegate += Method_Observer;
///Delegate与Event唯一区别就在于:Event提供了更严格的封装访问控制,其目的是为了防止其他类破坏委托的多播链,故不允许在声明事件的类外初始化或调用.
///即除了声明Event的类,其它类只能订阅(Subscribe,即+=)或取消订阅(Unsubscribe,即-=)该Event;
// /*1*/
It's OK
//subject.TestHandleDelegate = new Subject.TestHandleForReg(Method_Observer);
//
Error:The event 'Delegate_vs_Event.Subject.TestHandleEvent' can only appear on the left hand side of += or -= (except when used from within the type 'Delegate_vs_Event.Subject')
//subject.TestHandleEvent = new Subject.TestHandleForReg(Method_Observer);
// /*2*/
It's OK
///subject.TestHandleDelegate("test");
//
Error:The event 'Delegate_vs_Event.Subject.TestHandleEvent' can only appear on the left hand side of += or -= (except when used from within the type 'Delegate_vs_Event.Subject')
//subject.TestHandleEvent("test");
}
public void Method_Observer(string info)
{
Console.WriteLine("Observer's method [" + info + "]");
}
}
}
输出:
Call internal method result by [Delegate]
Observer's method [Delegate]
Method_Subject1
Call internal method result by [Event]
Observer's method [Event]
Method_Subject1
Method_Subject2
Static_Method_Subject