首页 > C#教程 阅读:19112

C#委托(Delegate)

C# 中的委托(Delegate)类似于 C 或 C++ 中的函数指针,是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。委托特别适用于实现事件和回调方法,所有的委托都派生自 System.Delegate 类。在实例化委托时,可以将委托的实例与具有相同返回值类型的方法相关联,这样就可以通过委托来调用方法。另外,使用委托还可以将方法作为参数传递给其他方法,

委托具有以下特点:
  • 委托类似于 C/C++ 中的函数指针,但委托是完全面向对象的。另外,C++ 中的指针会记住函数,而委托则是同时封装对象实例和方法;
  • 委托允许将方法作为参数进行传递;
  • 委托可用于定义回调方法;
  • 委托可以链接在一起,例如可以对一个事件调用多个方法;
  • 方法不必与委托类型完全匹配;
  • C# 2.0 版引入了匿名函数的概念,可以将代码块作为参数(而不是单独定义的方法)进行传递。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式都可编译为委托类型,这些功能现在统称为匿名函数。

声明委托

声明委托需要使用 delegate 关键字,语法格式如下:

delegate <return type> delegate-name(<parameter list>)

其中 return type 为返回值类型,delegate-name 为委托的名称,parameter list 为参数列表。

提示:委托可以引用与委托具有相同签名的方法,也就是说委托在声明时即确定了委托可以引用的方法。

实例化委托

委托一旦声明,想要使用就必须使用 new 关键字来创建委托的对象,同时将其与特定的方法关联。如下例所示:

public delegate void printString(string s); // 声明一个委托
...
printString ps1 = new printString(WriteToScreen); // 实例化委托对象并将其与 WriteToScreen 方法关联
printString ps2 = new printString(WriteToFile); // 实例化委托对象并将其与 WriteToFile 方法关联

【示例】下面通过具体的示例来演示委托的声明、实例化和使用,该委托可用于引用带有一个整型参数的方法,并返回一个整型值。
using System;
delegate int NumberChanger(int n); // 定义委托
namespace c.biancheng.net
{
 class Demo
 {
 static int num = 10;
 public static int AddNum(int p){
 num += p;
 return num;
 }
 public static int MultNum(int q){
 num *= q;
 return num;
 }
 public static int getNum(){
 return num;
 }
 static void Main(string[] args){
 // 创建委托实例
 NumberChanger nc1 = new NumberChanger(AddNum);
 NumberChanger nc2 = new NumberChanger(MultNum);
 // 使用委托对象调用方法
 nc1(25);
 Console.WriteLine("num 的值为: {0}", getNum());
 nc2(5);
 Console.WriteLine("num 的值为: {0}", getNum());
 Console.ReadKey();
 }
 }
}
运行结果如下:

num 的值为: 35
num 的值为: 175

多播委托(合并委托)

委托对象有一个非常有用的属性,那就是可以通过使用 + 运算符将多个对象分配给一个委托实例,同时还可以使用 - 运算符从委托中移除已分配的对象,当委托被调用时会依次调用列表中的委托。委托的这个属性被称为委托的多播,也可称为组播,利用委托的这个属性,您可以创建一个调用委托时要调用的方法列表。

注意:仅可合并类型相同的委托。

下面通过示例程序演示委托的多播:
using System;
delegate int NumberChanger(int n); // 定义委托
namespace c.biancheng.net
{
 class Demo
 {
 static int num = 10;
 public static int AddNum(int p){
 num += p;
 return num;
 }
 public static int MultNum(int q){
 num *= q;
 return num;
 }
 public static int getNum(){
 return num;
 }
 static void Main(string[] args){
 // 创建委托实例
 NumberChanger nc;
 NumberChanger nc1 = new NumberChanger(AddNum);
 NumberChanger nc2 = new NumberChanger(MultNum);
 nc = nc1;
 nc += nc2;
 // 调用多播
 nc(5);
 Console.WriteLine("num 的值为: {0}", getNum());
 Console.ReadKey();
 }
 }
}
运行结果如下:

num 的值为: 75

【示例】下面定义一个委托 printString,我们使用这个委托来调用两个方法,第一个把字符串打印到控制台,第二个把字符串打印到文件:
using System;
using System.IO;
namespace c.biancheng.net
{
 class Demo
 {
 static FileStream fs;
 static StreamWriter sw;
 // 委托声明
 public delegate void printString(string s);
 // 该方法打印到控制台
 public static void WriteToScreen(string str){
 Console.WriteLine("The String is: {0}", str);
 }
 // 该方法打印到文件
 public static void WriteToFile(string s){
 fs = new FileStream("./message.txt", FileMode.Append, FileAccess.Write);
 sw = new StreamWriter(fs);
 sw.WriteLine(s);
 sw.Flush();
 sw.Close();
 fs.Close();
 }
 // 该方法把委托作为参数,并使用它调用方法
 public static void sendString(printString ps)
 {
 ps("C语言中文网");
 }
 static void Main(string[] args){
 printString ps1 = new printString(WriteToScreen);
 printString ps2 = new printString(WriteToFile);
 sendString(ps1);
 sendString(ps2);
 Console.ReadKey();
 }
 }
}
运行上面的代码会在程序所在的目录下生成一个名为 message.txt 的文件,并输出一下内容:

The String is: C语言中文网

AltStyle によって変換されたページ (->オリジナル) /