C#中的委托
“委托”的基本概念
把一个方法(函数)作为另一个方法(函数)的参数
“委托”链
“委托”与C#的事件机制
(本文中的代码均在VS2005中运行过。启动VS2005,新建一个C#语言的控制台应用程序项目,将本文中代码复盖原自动生成的代码,启动调试,就可以看到运行结果)
一)委托的基本概念
面向对象编程的基本思想之一,就是将具有共同特征的某一类具体对象抽象为类。考察下面两个函数(方法):
void multiply (int m, int n){ return m*n; }
void divide (int x, int y){ return x/y; }
这两个函数(方法)有一个共同特征:具有相同的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);// “委托”类有一个参数为函数名的构造函数
特别的是,“委托”还可以象一般变量一样,用一个方法名对它进行赋值。下面的代码与上面的代码等效:
MyDelegate dg1 = multiply;
这一句也可读作:委托dg1来代理执行multiply函数。如果把dg1比作C 或 C++ 中的“函数指针”,这一句就是将dg1指向multiply函数的入口地址。(实际上,C#的“委托”就是用来替代C 或 C++ 中的“函数指针”的)。
下面一段完整的代码演示了“委托” 最基本、最简单的用法:
using System;
namespace DelegateSample//namespace:命名空间(类似于JAVA中的“包”)
{
//声明一个委托(Return Value为 int, Parament List为(int a, int b) )
public delegate int myDelegate(int a, int b);
class DelegateSample1
{
public static int multiply (int m, int n) //静态方法
{ return m*n; }
public static int divide(int x, int y)
{ return x/y; }
public static void Main(string[] args)
{
//以下用两种不同的方式创建委托的实例
myDelegate dg1,dg2;
dg1 = new myDelegate(multiply);
dg2 = divide;
Console.WriteLine(dg1(50,10));
Console.WriteLine(dg2(100,20));
Console.ReadLine();
}
}
}
运行结果,屏幕显示:
500
5
二)把一个方法(函数)作为另一个方法(函数)的参数
把一个方法(函数)作为另一个方法(函数)的参数,在较为复杂的程序设计中非常有用。-----因为它可以将类中的方法(函数)与具体的操作(方法的执行体)分离,这样,当具体的操作发生更改时,只需重新绑定该方法即可,而不用重写类。 C、C++语言是通过“函数指针”实现这一功能的,而C#则通过“委托”。
下面示例中的Add函数,就是将一个“委托”作为参数,任何一个与这个“委托”有相同签名的函数,都可以作为实参传递给它。
using System;
namespace DelegateSample
{
//声明一个委托(Return Value为 int, Parament List为(int a, int b) )
public delegate int myDelegate(int a, int b);
class DelegateSample1
{
public static int multiply (int m, int n) //静态方法
{ return m*n; }
public static int divide(int x, int y)
{ return x/y; }
//
public static int Add(int x1, int x2,int y1,int y2, myDelegate myCalcu)
{
return myCalcu(x1,x2) + myCalcu(y1,y2);
}
public static void Main(string[] args)
{
Console.WriteLine( Add(50,50,10,10,multiply) ); //计算 50*50 + 10*10
Console.WriteLine( Add(50,50,10,10,divide) ); //计算 50/50 + 10/10
Console.ReadLine();
}
}
}
运行结果,屏幕显示:
2600
2
三)“委托”链
“委托”可以用“+”运算符来组合,从而形成一个委托链。当然,只有具有相同签名的委托才可以组合。“-”运算符可用来从委托链中移除委托。
using System;
namespace DelegateSample
{
public delegate void myDelegate();
class DelegateSample2
{
public static void Function1() //静态方法
{ Console.WriteLine("this is Function1"); }
public static void Function2()
{ Console.WriteLine("this is Function2"); }
public static void Function3()
{ Console.WriteLine("this is Function3"); }
public writeline函数static void Main(string[] args)
{
myDelegate dg, dg1, dg2,dg3;
dg1 = Function1;
dg2 = Function2;
dg3 = Function3;
dg = dg1 + dg2; //dg1和da2组合成一个链dg
dg += dg3; // dg1、dg2和da3组合成一个链dg
dg();
Console.ReadLine();
dg -= dg1; //移除dg1
dg();
Console.ReadKey();
}
}
}
运行结果,屏幕显示:
this is Function1
this is Function2
this is Function3
按回车键后,屏幕显示:
this is Function2
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》
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论