委托是一种特殊的引用类型,其设计目的是表示函数指针。全部委托都来自[System.Runtime]System.MulticastDelegate
类型,它又派生自[System.Runtime]
。委托自己是密封的(就像值类型同样),所以不能从它们派生类型。api
对委托结构施加的限制与对枚举器结构施加的限制同样严格。委托没有字段、事件或属性。它们只能有两个或四个实例方法,而且这些方法的名称和签名是预约义的。安全
委托的两个强制方法是实例构造函数(.ctor)和Invoke
。实例构造函数返回void并接受两个参数;对定义被委托方法的类型的对象引用和对被委托的托管方法的函数指针。异步
这就引出了一个问题:若是你能获得一个函数指针,为何你还须要委托呢?为何不直接使用函数指针?能够,可是须要引入函数指针类型的字段或变量来保存这些指针——函数指针类型被认为是安全风险(由于指针值在从特定函数得到后能够修改),而且被认为是不可验证的。若是一个模块是不可验证的,它在禁用全部安全检查时,只能从本地驱动器以彻底信任模式执行。另外一个缺点是,在调用非托管方法时,托管函数指针不能封送到非托管函数指针,而委托能够封送。ide
第二个强制方法(Invoke)必须与委托方法具备相同的签名。两个强制的方法(.ctor和Invoke)足以容许委托用于同步调用,这是在调用线程被堵塞直到被调用方法返回以前一般的方法调用。第一个方法(.ctor)建立委托实例,并将其绑定到被委托的方法。Invoke方法用于对delegate方法进行同步调用。函数
当被调用的方法在公共语言运行时为此目的而建立的单独线程上执行而且不阻止调用线程时,委托还能够用于异步的调用。为了可以被异步调用,委托必须定义两个额外的方法:BeginInvoke
和EndInvoke
。线程
BeginInvoke
是线程启动程序,它接受委托方法的全部参数加上另外两个参数:类型为[System.Runtime]
的委托System.AsyncCallback
表示在调用完成时调用的回调方法,以及选择用于指示调用的最终状态的对象线程。BeginInvoke
返回接口[System.Runtime]
的实例System.IAsyncResult
,携带做为最后一个参数传递的对象,须要记住的是因为接口、委托和对象都是引用类型,因此当我说“接受委托”或“返回接口”时,实际指的是引用。设计
若是咱们打算在调用完成时当即受到通知,则必须指定AsyncCallback
委托。在异步调用完成时调用相应的回调方法。这种事件驱动技术是对异步调用完成做出反应的最普遍使用的方法。指针
咱们能够选择另外一种方法来监视异步调用线程的状态:主线程轮询。返回的接口具备bool get_IsCompleted()
方法,当异步调用完成时,该方法返回true,咱们能够不时地从主线程调用此方法,以肯定调用是否已经完成。code
咱们能够调用返回接口的另外一个方法get_AsyncWaitHandle
,它返回一个等待句柄,一个[System.Runtime]System.Threading
的实例。WaitHandle类,在得到等待句柄以后,咱们能够用任意本身喜欢的方式监视它(相似于Win32 api WaitForSingleObject和WaitForMultipleObjects的使用)。对象
若是选择使用轮询技术,则能够放弃回调函数并指定null而不是System.AsyncCallback
委托实例。
EndInvoke
方法采用[System.Runtime]System.IAsyncResult
接口,由BeginInvoke
做为其单个参数返回,并返回void。此方法等待异步调用完成,从而阻塞调用线程,所以在BeginInvoke
以后当即调用它至关于使用Invoke
的同步调用。最终必须调用EndInvoke
才能清除相应的运行时线程表条目,但应该在知道异步调用已完成时执行。
若是选择使用轮询技术,则能够放弃回调函数,而指定null而不是System.AsyncCallback
委托实例。
EndInvoke
方法采用[System.Runtime]
System.IAsyncResult
接口,由BeginInvoke
返回,做为它的单个参数,并返回void。这个方法等待异步调用完成,阻塞了调用线程,所以在BeginInvoke
以后当即调用它等同于使用Invoke
进行同步调用。最终必须调用EndInvoke
,以清除相应的运行时线程表条目,但应该在知道异步调用已经完成时执行。
委托的四个方法都是虚拟的,它们的实现由CLR自己提供的,用户不须要边写这些方法的主体。在定义delegate时,咱们能够简单的声明方法而不提供实现,以下所示:
.class nested public sealed auto ansi MyDelegate extends [System.Runtime]System.MulticastDelegate { .method public hidebysig specialname rtspecialname instance void .ctor( object 'object', native int 'method' ) runtime managed { // Can't find a body } // end of method MyDelegate::.ctor .method public hidebysig virtual newslot instance int32 Invoke( string s ) runtime managed { // Can't find a body } // end of method MyDelegate::Invoke .method public hidebysig virtual newslot instance class [System.Runtime]System.IAsyncResult BeginInvoke( string s, class [System.Runtime]System.AsyncCallback callback, object 'object' ) runtime managed { // Can't find a body } // end of method MyDelegate::BeginInvoke .method public hidebysig virtual newslot instance int32 EndInvoke( class [System.Runtime]System.IAsyncResult result ) runtime managed { // Can't find a body } // end of method MyDelegate::EndInvoke } // end of class MyDelegate
class Program { public delegate int MyDelegate (string s); static void Main(string[] args) { } }
参考:《Expert .NET 2.0 IL Assembler - Serge Lidin》