C#中的代理(委托)
/*
代理是一个可以引用方法的对象。当创建一个代理也就创建了一个引用方法的对象。
进而通过此引用就可以调用那个方法。因此代理可以调用它所指向的方法。
尽管方法不是对象,但他在内存中也是有物理地址的,此地址就是方法的入口点,
也就是方法被调用的地址。方法的地址可以赋给代理。
一旦一个代理引用了一个方法,就可以通过此代理来调用所有引用的方法,
而且代理引用的方法是可以改变的,这样同一个代理就可以调用多个不同的方法。
代理的主要优势就是允许指定调用方法,方法不是在编译时确定的,而是在运行时才决定的。
代理有关键字 delegate声明。 (代理类似与C/C++中的函数指针)
delegate ret-type name(parameter-list)
其中ret-type是代理所调用方法的返回值类型,name指定代理名称,
parameter-list指定代理调用的方法所需的参数列表。
一旦声明了代理,此代理就只能调用代理指定的与返回值类型和参数相吻合的方法。
使用代理时,最重要一点就是代理只能调用和其特征相吻合的方法。
这使得代理可以在运行期决定调用哪个方法。而且代理不但可以调用对象的实例化方法,
还可以调用类的静态方法。所有的问题都要归结于方法的特征要与代理相吻合。
*/
using System;
using System.Reflection;
delegate string strMod(string str); //声明代理
class DelegateTest
{
//使用连词符替换空格
string replaceSpaces(string a)
{
Console.WriteLine("Replace spaces with hyphens");
return a.Replace(' ','-');
}
//删除空格
string removeSpaces(string a)
{
string temp = "";
int i;
Console.WriteLine("Removeing spaces.");
for( i=0 ;i<a.Length;i++)
if(a[i] != ' ')
temp +=a[i];
return temp;
}
//字符串反序
string reverse(string a)
{
string temp = "";
int i;
Console.WriteLine("Reversing string.");
for(i=a.Length-1; i>=0;i--)
temp += a[i];
return temp;
}
public static void Main()
{
DelegateTest a = new DelegateTest();
strMod strOp = new strMod(a.replaceSpaces); //创建代理
string str;
//通过代理调用方法,
str = strOp("this is a test.");
Console.WriteLine("Resulting string: " +str);
Console.WriteLine();
strOp = new strMod(a.removeSpaces);
str = strOp("This is a test.");
Console.WriteLine("Resulting string " +str);
Console.WriteLine();
strOp = new strMod(a.reverse);
str = strOp("this is a test.");
Console.WriteLine("Resulting string:" +str);
}
}
/*
程序分析:本例程序声明了一个称为strMod的代理,带有一个string型的参数,返回了一个字符串。
在类DelegateTest中声明了三个静态方法,每个静态方法都有一个匹配特征。这三个方法都对字符串进行了某种修改。
在方法replaceSpace()中使用了字符中方法Replace(),用连词符替换空格。
在Main()方法中,创建了一个名为strOp的strMod型引用,它被赋给方法replaceSpace()的一个引用。
strMod strOp = new strMod(replaceSpace);
这里用replaceSpaces()方法只使用其名称而没有指定其他参数。
当实例化代理时,只指定想要引用的代理的方法名,同时所引用方法的特征与代理的声明相匹配。否则会导致编译错误。
因为strOp引用了replaceSpaces(),所以会调用方法replaceSpaces(),然后strOp赋给了发方法removeSpces()的一个引用,
当调用strOp会调用方法removeSpces(),最后strOp被赋给了发方法reverse()的一个引用,
而且当调用strOp时就会调用方法reverse()方法。
小结:代理是引用方法的对象。只有在运行期,才能使用代理调用已知方法。
使用代理的主要原因有:
* 第一,代理支持事件;
* 第二,使用代理程序可以在运行期执行一个方法而不是在编译时精确知道是什么方法。
*/