C#编程指南----委托

委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。
public   delegate   void  Del( string  message);

构造委托对象时,通常提供委托将包装的方法的名称或使用匿名方法。实例化委托后,委托将把对它进行的方法调用传递给方法。调用方传递给委托的参数被传递给方法,来自方法的返回值(如果有)由委托返回给调用方。这被称为调用委托。可以将一个实例化的委托视为被包装的方法本身来调用该委托。例如:

//  Create a method for a delegate.
public   static   void  DelegateMethod( string  message)
{
    System.Console.WriteLine(message);
}
//  Instantiate the delegate.
Del handler  =  DelegateMethod;

//  Call the delegate.
handler( " Hello World " );

在控制台中将收到下面的输出:

The number is: 3

在将委托用作抽象概念时,MethodWithCallback 不需要直接调用控制台 -- 设计它时无需考虑控制台。MethodWithCallback 的作用只是准备字符串并将该字符串传递给其他方法。此功能特别强大,因为委托的方法可以使用任意数量的参数。

将委托构造为包装实例方法时,该委托将同时引用实例和方法。除了它所包装的方法外,委托不了解实例类型,所以只要任意类型的对象中具有与委托签名相匹配的方法,委托就可以引用该对象。将委托构造为包装静态方法时,它只引用方法。考虑下列声明:

public   class  MethodClass
{
    
public void Method1(string message) { }
    
public void Method2(string message) { }
}

加上前面显示的静态 DelegateMethod,现在我们有三个方法可由 Del 实例进行包装。

调用委托时,它可以调用多个方法。这称为多路广播。若要向委托的方法列表(调用列表)中添加额外的方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。例如:

MethodClass obj  =   new  MethodClass();
Del d1 
=  obj.Method1;
Del d2 
=  obj.Method2;
Del d3 
=  DelegateMethod;

// Both types of assignment are valid.
Del allMethodsDelegate  =  d1  +  d2;
allMethodsDelegate 
+=  d3;

此时, allMethodsDelegate 在其调用列表中包含三个方法 -- Method1Method2DelegateMethod。原来的三个委托 d1d2d3 保持不变。调用 allMethodsDelegate 时,将按顺序调用所有这三个方法。如果委托使用引用参数,则引用将依次传递给三个方法中的每个方法,由一个方法引起的更改对下一个方法是可见的。如果任一方法引发了异常,而在该方法内未捕获该异常,则该异常将传递给委托的调用方,并且不再对调用列表中后面的方法进行调用。如果委托具有返回值和/或输出参数,它将返回最后调用的方法的返回值和参数。若要从调用列表中移除方法,请使用减法运算符或减法赋值运算符(“-”或“-=”)。例如:
// remove Method1
allMethodsDelegate  -=  d1;

//  copy AllMethodsDelegate while removing d2
Del oneMethodDelegate  =  allMethodsDelegate  -  d2;

在调用列表中具有多个方法的委托派生自 MulticastDelegate,这是 System.Delegate 的子类。由于两个类都支持 GetInvocationList,所以上面的代码在两种情况下都适用。

多路广播委托广泛用于事件处理中。事件源对象向已注册接收该事件的接收方对象发送事件通知。为了为事件注册,接收方创建了旨在处理事件的方法,然后为该方法创建委托并将该委托传递给事件源。事件发生时,源将调用委托。然后,委托调用接收方的事件处理方法并传送事件数据。给定事件的委托类型由事件源定义。有关更多信息,请参见事件(C# 编程指南)

在编译时,对分配了两种不同类型的委托进行比较将产生编译错误。如果委托实例静态地属于类型 System.Delegate,则允许进行比较,但在运行时将返回 false。例如:

delegate   void  Delegate1();
delegate   void  Delegate2();

static   void  method(Delegate1 d, Delegate2 e, System.Delegate f)
{
    
// Compile-time error.
    
//Console.WriteLine(d == e);

    
// OK at compile-time. False if the run-time type of f 
    
//is not the same as that of d.
    System.Console.WriteLine(d == f);
}

你可能感兴趣的:(C#)