比如我们定义下面的委托:
public delegate void DelSay(string s);
那么使用DelSay声明的委托对象仅代表返回值是void,参数为一个字符串的方法。或者,我们如下定义委托:
delegate int CallCumpute(int i,int j);
上面定义的CallCumpute委托所创建的委托对象只能代表任何返回值是整型,参数为两个整型的方法。实际上,委托的定义有个技巧,那就是你先定义要委托的方法,然后把这个方法的声明部分拷贝过来加上一个delegate关键字就是要定义的委托。另外,对于委托和其委托的方法并不在意访问修饰符是否不同,只要是和委托返回类型和参数类型相同的方法,委托对象都是可以代表的。
我们再来看上面提到那个例子的完整代码:
using System;
using System.Collections.Generic;
using System.Text;
namespace MyDelegate
{
//定义委托类型
public delegate void MySayDeleage();
class Me
{
public void SayHello() { Console.WriteLine("你好,很高兴认识你!");}
public void SayLoveYou() { Console.WriteLine("我爱你!"); }
public void SayBye() { Console.WriteLine("再见!"); }
}
class Program
{
static void Main(string [] args)
{
Me me=new Me();
//定义委托对象mySay
MySayDeleage mySay=new MySayDeleage(me.SayHello);
mySay();
mySay=new MySayDeleage(me.SayLoveYou);
mySay();
mySay=new MySayDeleage(me.SayBye);
mySay();
}
}
}
运行结果是:
你好,很高兴认识你!
我爱你!
再见!
在上面的这个例子当中我们定义了一个MySayDeleage类型的委托,这个委托类型可以代表返回值是void、参数是空的方法。这里要注意,要委托一个方法,只需将这个方法的方法名传入委托类型的构造方法中即可创建委托对象(传入的方法不包括参数,这一点很多人有疑问,如果熟悉函数指针你就知道为什么了,实际上我们大可把方法看作一个对象,方法名即对象名)。定义一个委托类型相比定义一个类来说显得怪怪的,当然这种奇怪是因为它的任务所造成的,我们说它要代表一个方法,就必须用某种方式来说明它能代表什么方法,C#中就用上面这种方式,奇怪也没用。
上面的例子是针对类的实例方法的,要委托类的实例方法,要先创建类的实例,因为只有创建了类的实例,方法才会真正的存在于内存中,我们才可以将其委托。当然我们知道还有一种静态方法,静态方法在类定义完后就存在了,既然存在就可以委托了,所以委托静态方法,不需要类的实例,直接委托就可以了。如:
class Program
{
public static void SayHello() { Console.WriteLine("你好,很高兴认识你");}
static void Main(string [] args)
{
MySayDeleage t=new MySayDeleage(Program.SayHello);
t();
}
}
还要注意一点,要调用委托的方法,需要用委托对象加参数,如果参数为空也不能少了小括号,如上面那个t()就表示调用委托对象t代表的方法。为了弄清楚这一点,我们再来看一个带参数的例子:
using System;
using System.Collections.Generic;
using System.Text;
namespace MyDelegate
{
public delegate int CalculateCall(int a,int b);
class Program
{
public static int Add(int x,int y) { return x + y; }
public static int Substract(int x, int y) { return x - y ; }
static void Main(string [] args)
{
CalculateCall cal=new CalculateCall(Program.Add);
int result=cal(4,6);
Console.WriteLine("结果是{0}",result);
}
}
}
上例使用委托对象cal调用它代表的方法,并传递参数和返回结果。仔细观察会发现委托对象调用方法的方式和方法一样,也需要参数,也有返回值,所以很多人这样记忆和理解委托:委托对象就是方法的别名,如cal就是Add这个方法的别名,这样理解有时会很有帮助。另外最重要的一点,要注意委托定义的位置,虽然它的定义像方法,但是它是和类、接口等一样是一个数据类型,所以它的位置可以直接出现在命名空间之下,而不一定要在类的内部定义。