现在的位置: 首页 > 综合 > 正文

C#编程指南—-委托

2013年07月11日 ⁄ 综合 ⁄ 共 2332字 ⁄ 字号 评论关闭
委托是一种安全地封装方法的类型,它与 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);
}

抱歉!评论已关闭.