委托在某种程度上提供了间接的方法。换言之,不需要直接指定一个行为,而是将这个行为用某种方式“包含”在一个对象中。这个对象可以象其他任何对象那样使用。在这个对象中,可以执行封装的行为。可以将委托类型看做只定义了一个方法的接口,将委托的实例看做实现了那个接口的一个对象。
委托的4个基本条件:
1)声明委托类型;
2)必须有一个方法包含了要执行的代码;
3)必须创建一个委托实例;
4)必须调用(invoke)委托实例。
1.声明委托类型
委托类型实际上只是参数类型的一个列表以及一个返回类型。它规定了类型的实例能表示的操作。以如下方式声明一个委托类型。
delegate void StringProcessor(string input);
这里的重点是StringProcessor其实是一个类型。它有方法,可以创建它的实例,并将引用传递给实例。
2.为委托实例的操作找到一个恰当的方法
找到(或者写)一个方法,它能做我们想做的事情,同时具有和委托类型相同的签名。
来看看以下StringProcessor实例的5个备选的方法签名:
void PrintString(string x)
void PrintInteger(int x)
void PrintTwoString(string x, string y)
int GetStringLength(string x)
void PrintObject(object x)
我们来看,第一个方法完全符合要求,所以可以用它创建一个委托实例。第二个方法虽然也有一个参数但不是string类型,所以不兼容StringProcessor。第三个方法参数数量不匹配,所以不兼容。第四个方法有正确的参数列表,但是返回类型不是void(如果委托类型有返回类型,方法的返回类型也必须与之匹配)。第五个方法比较有趣,任何时候调用一个StringProcessor实例,都可以调用具有相同的参数的PrintObject方法,这是由于string是从object派生的。
3.创建委托实例
既然已经有了一个委托类型和一个有正确签名的方法,接着可以创建委托类型的一个实例,指定在调用委托实例时就执行该方法。至于具体用什么形式的表达式来创建委托实例,取决于操作使用实例方法还是静态方法。如果操作是静态方法,指定类型名称就可以了。如果操作时实例方法,就需要先创建类型(或者它的派生类型)的一个实例。这和平时调用方法是一样的。
假定PrintString是StaticMethods类型中的一个静态方法,在InstanceMethods类型中是一个实例方法。下面是创建一个StringProcessor实例的两个例子:
StringProcessor proc1, proc2;
proc1=new StringProcessor(StaticMethods.PrintString);
InstanceMethods instance=new InstanceMethods();
prce2=new StringProcessor(instance.PrintString);
4.调用委托实例
这是很简单的事情(仅对同步调用而言)-调用一个委托实例的方法就可以了。这个方法本身被称为Invoke。在委托类型中,这个方法以委托类型的形式出现,并且具有与委托类型的声明中所指定的相同的参数列表和返回类型。调用Invoke会执行委托实例的操作,向它传递在调用Invoke时指定的任何参数。让我们看下下图更好的理解:
下面来看一个完整的代码:
using System;//声明委托类型delegate void StringProcessor(string input);class Person{ string name; public Person(string name) { this.name = name; } //声明兼容的实例方法 public void Say(string message) { Console.WriteLine("{0}说:{1}", name, message); }}class Background{ //声明兼容的静态方法 public static void Note(string note) { Console.WriteLine("({0})",note); }}class SimpleDelegateUse{ static void Main() { Person jon = new Person("Jon"); Person Tom = new Person("Tom"); //创建3个委托实例 StringProcessor jonsVoice, tomsVoice, background; jonsVoice = new StringProcessor(jon.Say);//实例方法 tomsVoice = new StringProcessor(Tom.Say);//实例方法 background = new StringProcessor(Background.Note);//静态方法 //调用委托实例 jonsVoice("Hello,World!"); tomsVoice.Invoke("欢迎观临我的博客!"); background("版权所有爱智旮旯!"); Console.Read(); }}
效果如图: