(C#)委托
(2011-11-17 15:49:48)
标签:
委托csharp |
分类: C#笔记 |
委托
(本文中的代码均在VS2005中运行过。启动VS2005,新建一个C#语言的控制台应用程序项目,将本文中代码复盖原自动生成的代码,启动调试,就可以看到运行结果)
一)委托的基本概念
面向对象编程的基本思想之一,就是将具有共同特征的某一类具体对象抽象为类。考察下面两个函数(方法):
void multiply (int m, int n){ return m*n; }
void divide
这两个函数(方法)有一个共同特征:具有相同的Parament List and Return Value(又可称为具有相同的签名)。在C#中,可以把这种具有相同签名的函数(方法)抽象为一种“类”-----这种“类”,在C#中被称作“委托(delegate)”。
声明“委托”的关键字是“delegate”。对于上面的两个方法,我们可以用如下语句声明一个名为MyDelegate的“委托”:
public delegate void MyDelegate(int a, int b);
创建“委托”实例的语法与创建其它类的实例一样,下面语句就创建了一个名为dg1的实例,可以用它来替代multiply函数:
MyDelegate dg1 = new MyDelegate(multiply);// “委托”类有一个参数为函数名的构造函数
特别的是,“委托”还可以象一般变量一样,用一个方法名对它进行赋值。下面的代码与上面的代码等效:
这一句也可读作:委托dg1来代理执行multiply函数。如果把dg1比作C 或 C++ 中的“函数指针”,这一句就是将dg1指向multiply函数的入口地址。(实际上,C#的“委托”就是用来替代C 或 C++ 中的“函数指针”的)。
下面一段完整的代码演示了“委托” 最基本、最简单的用法:
using System;
namespace DelegateSample//namespace:命名空间(类似于JAVA中的“包”)
{
dg1 = new myDelegate(multiply);
}
运行结果,屏幕显示:
500
5
二)把一个方法(函数)作为另一个方法(函数)的参数
把一个方法(函数)作为另一个方法(函数)的参数,在较为复杂的程序设计中非常有用。-----因为它可以将类中的方法(函数)与具体的操作(方法的执行体)分离,这样,当具体的操作发生更改时,只需重新绑定该方法即可,而不用重写类。 C、C++语言是通过“函数指针”实现这一功能的,而C#则通过“委托”。
下面示例中的Add函数,就是将一个“委托”作为参数,任何一个与这个“委托”有相同签名的函数,都可以作为实参传递给它。
using System;
namespace DelegateSample
{
}
运行结果,屏幕显示:
2600
三)“委托”链
“委托”可以用“+”运算符来组合,从而形成一个委托链。当然,只有具有相同签名的委托才可以组合。“-”运算符可用来从委托链中移除委托。
using System;
namespace DelegateSample
{
}
运行结果,屏幕显示:
this is Function1
this is Function2
this is Function3
按回车键后,屏幕显示:
this is Function3
前面说过,“委托”类似于C语言中的函数指针。如果说一个函数指针存放一个函数的入口地址,则一个“委托”可以存放多个函数的入口地址(当然这些函数必须有相同的返回值和参数)。
“委托”的这个特点,是构建C#的事件机制基础之一。
四)“委托”与C#的事件机制
C#的事件机制,可以简单描述如下:
假设A对象有一个e事件,当e事件发生时,B1、B2、B3……等众多对象都会执行各自的e事件响应函数。-----这一过程,用C#语言是这样来实现:
在A对象中设置一个委托链,B1、B2、B3……等对象可以将各自的事件响应函数用“+=”运算符加入到这个委托链中(此操作又称注册)。这样,当A对象的e事件发生时,就可以通过这个委托链来回调B1、B2、B3……等对象的e事件响应函数。
为了安全起见,C#将上述的A对象的委托链进一步包装为event , 经过包装的event,实质上是加了保护层的delegate, 它仅允许其它对象对它进行“+=”或“-=”操作,以保证A对象的“封装性”不受影响)。
详见《事件event》

加载中…