Before formally defining .NET delegates, let’s gain a bit of perspective. (在正式定义.NET delegate之前,让我们获得一点点透视)Historically speaking, the
Windows API made frequent use of C-style function pointers to create entities termed callback functions or simply callbacks. (从历史的角度来说,Windows
API频繁使用C语言风格的函数指针来创建实体称作回调函数或简而言之回调)
Using callbacks, programmers were able to configure one function to
report back to (call back) another function in the application. (使用回调函数,程序员可以配置一个函数回调这个应用程序中的另一个函数)
Using this approach, Win32 developers
were able to handle button clicking, mouse moving, menu selecting, and general bidirectional
communications between two programming entities.
The problem with standard C-style callback functions is that they represent little more than a
raw address in memory. Ideally, callbacks could be configured to include additional type-safe information
such as the number of (and types of) parameters and the return value (if any) of the method
pointed to. Sadly, this is not the case in traditional callback functions, and, as you may suspect, can
therefore be a frequent source of bugs, hard crashes, and other runtime disasters. Nevertheless, callbacks
are useful entities.
In the .NET Framework, callbacks are still possible, and their functionality is accomplished in a
much safer and more object-oriented manner using delegates. In essence, a delegate is a type-safe
object that points to another method (or possibly a list of methods) in the application, which can be
invoked at a later time. Specifically speaking, a delegate object maintains three important pieces of
information:
从本质上来说,代理是一个应用中指向另一个方法(也可能是一系列方法)的类型安全的对象,这个对象稍后可以被调用。具体来说,一个代理对象包括三类重要信息:
• The address of the method on which it makes calls
• The arguments (if any) of this method
• The return value (if any) of this method
它调用的方法的地址
这个方法的参数
这个方法的返回值
Unlike C(++) function pointers, .NET delegates can point to either static or instance methods
Once a delegate has been created and provided the necessary information, it may dynamically
invoke the method(s) it points to at runtime. As you will see, every delegate in the .NET Framework
(including your custom delegates) is automatically endowed with the ability to call its methods
synchronously or asynchronously. This fact greatly simplifies programming tasks, given that we
can call a method on a secondary thread of execution without manually creating and managing a
Thread object.
Defining a Delegate in C#
When you want to create a delegate in C#, you make use of the delegate keyword. The name of your
delegate can be whatever you desire. However, you must define the delegate to match the signature
of the method it will point to. For example, assume you wish to build a delegate named BinaryOp
that can point to any method that returns an integer and takes two integers as input parameters:
// This delegate can point to any method,
// taking two integers and returning an integer.
public delegate int BinaryOp(int x, int y);
Delegates can also “point to” methods that contain any number of out or ref parameters (as
well as array parameters marked with the params keyword).
代理也能指向那些方法包含out或者ref参数的方法(以及用params关键字标记的
数组参数)For example, assume the following
delegate type:
public delegate string MyOtherDelegate(out bool a, ref bool b, int c);
The signatures of the Invoke() and BeginInvoke() methods look as you would expect; however,
check out the EndInvoke() method, which now includes the set of all out/ref arguments defined by
the delegate type:
sealed class MyOtherDelegate : System.MulticastDelegate
{
public MyOtherDelegate (object target, uint functionAddress);
public string Invoke(out bool a, ref bool b, int c);
public IAsyncResult BeginInvoke(out bool a, ref bool b, int c,
AsyncCallback cb, object state);
public string EndInvoke(out bool a, ref bool b, IAsyncResult result);
}
To summarize, a C# delegate definition results in a sealed class with three compiler-generated
methods whose parameter and return types are based on the delegate’s declaration.
总之,C#的delegate定义产生了一个带有三个编译器产生的方法的封装类,这些方法的参数与返回值基于delegate的声明)
The following
pseudo-code approximates the basic pattern:
// This is only pseudo-code!
public sealed class DelegateName : System.MulticastDelegate
{
public DelegateName (object target, uint functionAddress);
public delegateReturnValue Invoke(allDelegateInputRefAndOutParams);
public IAsyncResult BeginInvoke(allDelegateInputRefAndOutParams,
AsyncCallback cb, object state);
public delegateReturnValue EndInvoke(allDelegateRefAndOutParams,
IAsyncResult result);
}
The System.MulticastDelegate and
System.Delegate Base Classes
So, when you build a type using the C# delegate keyword, you indirectly declare a class type that
derives from System.MulticastDelegate.
因此,当你构造一个使用C# delegate关键字的类型时,你间接地声明了一个类类型派生自System.MulticastDelegate.
1. 派生的
This class provides descendents with access to a list that
contains the addresses of the methods maintained by the delegate type, as well as several additional
methods (and a few overloaded operators) to interact with the invocation list. Here are some select
members of System.MulticastDelegate:
public abstract class MulticastDelegate : Delegate
{
// Returns the list of methods "pointed to."
public sealed override Delegate[] GetInvocationList();
// Overloaded operators.
public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2);
public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2);
一个简单的delegate example
using System;
//this delegate can point to any method,
//taking two integers and returning an integer
public delegate int BinaryOp(int x,int y);
//This class contains methods BinaryOp will
//point to
public class SimpleMath
{
public static int Add(int x, int y)
{
return x + y;
}
public static int Subtract(int x, int y)
{
return x - y;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("*****Simple Delegate Example******/n");
//Create a BinaryOp object that
//"Point to "SimpleMath.Add()
BinaryOp b = new BinaryOp(SimpleMath.Add);
//invoke Add() method indirectly using delegate object
Console.WriteLine("10+10 is {0}", b(10, 10));
Console.ReadLine();
}
}