C#语言系列讲座(9)委派

转载 2004年09月01日 12:09:00
委派

委派是C#引入的一种新的数据类型,它非常类似于C/C++中的函数指针,常常用于在编译时未绑定的动态方法调用。与函数指针不同的是委派在C#中完全实现了面向对象,它既可以引用静态方法,也可以引用实例方法,而函数指针只能引用静态方法。C#中的委派同时也是类型安全的。

作为一种面向对象的数据类型,委派的使用分为三步:委派声明,委派实例化和委派调用。委派声明就是定义一个封装特定参数类型和返回值类型的方法体(静态方法或实例方法)的数据类型,看下面的示例:

delegate int Compute (int left, int right);

可以看到,委派类型Compute包含了方法的两个要素: 参数类型和返回值类型。委派类型和方法只有满足下面两个条件,才能说它们是兼容的:

1. 参数的数量相同,并且它们的类型也按顺序相同;

2. 返回值相同。

委派类型相同指的是它们声明的类型为同一类型(名字一样)。而委派实例相等则是指它们绑定的方法为同一个方法,或相同的方法按相同的顺序组成的方法链,而它们本身的类型只要兼容即可(同样满足上面两个条件),不必强求同名。

委派实例化就是将委派类型绑定到特定方法的过程,和其他对象的实例化相似,都需要用new语句,只是必须接受和该委派类型兼容的方法名作为new语句的参数。如果是实例方法,必须采用两者中间加点号的方式同时提供实例对象和方法。

委派实例化后就可以像调用方法一样进行委派调用了。下面是一个完整的例子,比较典型地展示了通常使用委派的三个步骤:

using System;

delegate int Compute(int left, int right);

//委派类型声明

class A

{

public int Mul(int num1, int num2)

{ return num1*num2;

}

}

class Test

{

public static int Add(int num1, int num2)

{ return num1+num2;

}

static void Main()

{ Compute c1=new Compute(Add);

//静态方法的实例化

A a=new A();

Compute c2=new Compute(a.Mul);

//实例方法的实例化

int r1=c1(2,3);//委派调用

int r2=c2(2,3);//委派调用

Console.WriteLine(r1);

Console.WriteLine(r2);

}

}

委派组合

委派组合是指一个委派类型可以同时绑定多个可调用的方法。由于绑定多个方法,C#规定组合委派的返回类型必须为void。当然,这些方法的参数类型也必须都和组合委派的参数类型兼容。委派组合采用“+”或“+=”来将两个委派类型合并为一个新的组合委派类型; 采用“-”或“-=”来从组合委派类型上移除已经绑定一个方法的委派实例或绑定多个方法的组合委派实例。

需要注意的是在做委派的组合和移除操作的时候,参与操作的委派类型必须相同——注意是“相同”不是“相等”。看下面的例子:

using System;

delegate void MyDelegate(string s);

class Test

{

public static void Hello(string s)

{

Console.WriteLine(“Hello, {0}!”, s);

}

public static void Goodbye(string s)

{

Console.WriteLine(“Goodbye, {0}!”, s);

}

public static void Main()

{

MyDelegate a, b, c, d;

a = new MyDelegate(Hello);

b =new MyDelegate(Goodbye);

c = a + b;//委派的组合

d = c - a;//委派的移除

a(“A”);

b(“B”);

c(“C”);

d(“D”);

}

}

程序输出:

Hello, A!

Goodbye, B!

Hello, C!

Goodbye, C!

Goodbye, D!

可以看到在委派组合后,组合委派类型C同时绑定了两个方法Hello(string s)和Goodbye(string s),从它的输出可以看到这一点。

需要注意的是组合委派中的方法调用是有顺序的,如果在上面的例子中修改“c = a + b; ”为“c=b + a; ”,将看到输出序列的改变。

同样委派的移除也是有顺序的,它总是从绑定的委派实例中的最后开始搜索需要移出的委派实例——注意这里的移除是以委派实例为单位的,而不是以方法为单位。可以将上面的例子进行修改,再看看结果:

public static void Main()

{

MyDelegate a, b, c, d;

a = new MyDelegate(Hello);

b =new MyDelegate(Goodbye);

c = a+b+a;//委派的组合

b+=b;//委派的组合

d = c - b;//委派的移除

a(“A”);

b(“B”);

c(“C”);

d(“D”);

}

一个比较好的全排列算法(C语言)

  全排列算法我有一个比较好的全排列算法,我验证了3、4、5的结果是正确的。程序中没有使用递归,只是几个循环,速度还令人满意。在C466A,Win2000的机器上,进行8个数字的全排列,结果不显示,重...
  • eWolf
  • eWolf
  • 2001年08月04日 19:57
  • 2789

CCF 201609-2 火车购票 解题报告 简单模拟

题目: 问题描述 试题编号: 201612-2 试题名称: 火车购票 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述   请实现...
  • xiaoli_nu
  • xiaoli_nu
  • 2016年10月15日 12:25
  • 4317

火车购票问题(2016CCF)

问题描述 请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配。 假设一节车厢有20排、每一排5个座位。为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排 ...
  • cs9426478
  • cs9426478
  • 2016年09月14日 21:22
  • 4100

C#语言系列讲座18讲

  • 2008年06月27日 23:48
  • 156KB
  • 下载

C#语言系列讲座

  • 2007年09月14日 08:39
  • 14KB
  • 下载

C#线程系列讲座(5):同步技术之Monitor

转自:http://www.cnblogs.com/nokiaguy/archive/2008/07/31/1257625.html  在上一讲介绍了使用lock来实现线程之间的同步。实际上...
  • KAIFEIXIONGDI
  • KAIFEIXIONGDI
  • 2012年04月14日 15:52
  • 471

C#线程系列讲座(4):同步与死锁

虽然线程可以在一定程度上提高程序运行的效率,但也会产生一些副作用。让我们先看看如下的代码:     class Increment      {         private int ...
  • r798303142b
  • r798303142b
  • 2012年06月02日 10:47
  • 312

C#线程系列讲座(4):同步与死锁

转自:http://www.cnblogs.com/nokiaguy/archive/2008/07/25/1251756.html 虽然线程可以在一定程度上提高程序运行的效率,但也会产生一...
  • KAIFEIXIONGDI
  • KAIFEIXIONGDI
  • 2012年04月14日 15:45
  • 323

C#线程系列讲座(5):同步技术之Monitor

http://www.cnblogs.com/nokiaguy/archive/2008/07/31/1257625.html 在上一讲介绍了使用lock来实现线程之间的同步。实际上,这个lock是...
  • byondocean
  • byondocean
  • 2011年12月06日 21:18
  • 426

C#线程系列讲座(3):线程池和文件下载服务器

http://www.cnblogs.com/nokiaguy/archive/2008/07/16/1244746.html    如果设计一个服务器程序,每当处理用户请求时,都开始一个线程,将会...
  • byondocean
  • byondocean
  • 2011年12月06日 21:15
  • 441
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#语言系列讲座(9)委派
举报原因:
原因补充:

(最多只允许输入30个字)