【www.gdgbn.com--其它】
delegate是c#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它只能持有与它的签名相匹配的方法的引用。它所实现的功能与c/c++中的函数指针十分相似。它允许你传递一个类a的方法m给另一个类b的对象,使得类b的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数指针不具备的优点。首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。
.net 中的委托类似于 c 或 c++ 中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与 c 或 c++ 中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。 委托声明定义一种类型,它用一组特定的参数以及返回类型封装方法。对于静态方法,委托对象封装要调用的方法。对于实例方法,委托对象同时封装一个实例和该实例上的一个方法。如果您有一个委托对象和一组适当的参数,则可以用这些参数调用该委托。 委托的一个有趣且有用的属性是,它不知道或不关心自己引用的对象的类。任何对象都可以;只是方法的参数类型和返回类型必须与委托的参数类型和返回类型相匹配。这使得委托完全适合“匿名”调用。
[ ] [ accessmodifier ] _ [ shadows ] delegate [ sub | function ] name [( of typeparamlist )] [([ parameterlist ])] [ as type ]
实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate:
1.声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。
2.创建delegate对象,并将你想要传递的函数作为参数传入。
3.在要实现异步调用的地方,通过上一步创建的对象来调用方法。
下面是一个简单的例子:
用delegate解决(异步调用):
public void setscore(int value)
{
if (value > 100 || value < 0)
{
console.out.writeline("分数不对");
}
else
{
score = value;
if (advisedelegateinstance!= null)
{
advisedelegateinstance.begininvoke(score,null,null);
}
}
}
不过这样我们失去了老师的返回结果,不知道有没有及格了。
采用轮讯的方法去获得结果:
public void setscore(int value)
{
if (value > 100 || value < 0)
{
console.out.writeline("分数不对");
}
else
{
score = value;
if (advisedelegateinstance!= null)
{
iasyncresult res = advisedelegateinstance.begininvoke(score,null, null);
while( !res.iscompleted ) system.threading.thread.sleep(1);
string result = advisedelegateinstance.endinvoke(res);
console.out.writeline("学生收到老师返回的结果t"+result);
}
}
}
不过这样主线程又被阻塞了,采用回调的方式: (注:接口也可以采用回调的方式获得返回值)
public void setscore(int value)
{
if (value > 100 || value < 0)
{
console.out.writeline("分数不对");
}
else
{
score = value;
if (advisedelegateinstance!= null)
{
iasyncresult res = advisedelegateinstance.begininvoke(score, new system.asynccallback(callbackmethod), null);
}
}
}
private void callbackmethod(iasyncresult asyncresult)
{
string result = advisedelegateinstance.endinvoke(asyncresult);
console.out.writeline("学生收到老师返回的结果t" + result);
}
这样就比较得到了一个比较好的解决方案了。我们再来看看begininvoke的第四个参数是干吗的呢?
public void setscore(int value)
{
if (value > 100 || value < 0)
{
console.out.writeline("分数不对");
}
else
{
score = value;
if (advisedelegateinstance!= null)
{
advisedelegateinstance.begininvoke(score, new system.asynccallback(callbackmethod), "idior");
}
}
}
private void callbackmethod(iasyncresult asyncresult)
{
string result = advisedelegateinstance.endinvoke(asyncresult);
string stateobj=(string)asyncresult.asyncstate;
console.out.writeline("学生{0}收到老师返回的结果t" + result,stateobj.tostring());
}
usingsystem;
publicclassmydelegatetest
{
//步骤1,声明delegate对象
publicdelegatevoidmydelegate(stringname);
//这是我们欲传递的方法,它与mydelegate具有相同的参数和返回值类型
publicstaticvoidmydelegatefunc(stringname)
{
console.writeline("hello,{0}",name);
}
publicstaticvoidmain()
{
//步骤2,创建delegate对象
mydelegatemd=newmydelegate(mydelegatetest.mydelegatefunc);
//步骤3,调用delegate
md("sam1111");
}
}
输出结果是:hello,sam1111
接口(interface)
你必须注意的另一个点是一个delegate和一个接口之间的相似性,因为它们都将规范和执行分离开来。它们允许开发人员建立与规范相符合的执行。除此之外,方法标记必须是被指定和相兼容。
所以,你什么时候使用接口?以及你什么时候使用delegates?微软提供了以下的指导思想。
在以下情况下使用delegates很有用:
调用一个单一方法。
一个类要进行方法规范(method specification)的多种执行。
使用一个静态方法来执行规范。
想获得类似事件设计的模式。
调用者没有必要知道或获得方法定义的对象。
执行的提供者想将规范的执行“分发”成一些选择性的部分。
在以下情况下使用接口非常有好处:
规范指定一套即将被调用的方法。
特别的,一个类只执行规范一次。
接口的调用者想通过接口类型以获得其它接口或类