解析.Net 4.0 中委托delegate的使用详解

.Net中的委托从功能上讲和c语言或者c++中的方法指针类似,可以像调用方法一样调用委托完成某个功能,或返回某类结果。但是.Net毕竟是更高级的语言,委托Delegate也更高级了,委托是一种数据接口,它包含调用目标和调用方法的指针;而在.Net中定义的委托都继承自MulticastDelegate即多播委托,所谓的多播委托是指可以包含多个调用方法的委托。
一. 先来看下委托的定义:
如下C#代码定义委托
public delegate void DoSomething(int times);
委托的定义包含5个部分
1) public表示委托的可访问性
2) delegate关键字表示要定义一个委托
3) void表示委托定义方法的返回值
4) DoSomething是委托的名字
5) (int times) 是委托方法的参数列表,此处的参数列表可以包括ref参数,也可以有out参数,同样也可以有parms可变数量参数;需要注意如果委托中有多个调用方法,使用out参数时只能返回委托最后执行成功的一个委托方法的计算值
在C#中定义委托非常简单,只比方法定义的返回值之前多一个delegate关键字即可。
可是我们知道所有的用户定义委托都继承自MulticastDelegate;而MulticastDelegate是一个类;所以自定义的委托肯定也是一个类;看下上述代码的IL代码就可以证明我们的推断:

复制代码 代码如下:


.class public auto ansi sealed delegates.DoSomething
    extends [mscorlib]System.MulticastDelegate
{
    // Methods
    .method public hidebysig specialname rtspecialname
        instance void .ctor (
            object 'object',
            native int 'method'
        ) runtime managed
    {
    } // end of method DoSomething::.ctor

    .method public hidebysig newslot virtual
        instance void Invoke (
            int32 times
        ) runtime managed
    {

    } // end of method DoSomething::Invoke

 
    .method public hidebysig newslot virtual
        instance class [mscorlib]System.IAsyncResult BeginInvoke (
            int32 times,
            class [mscorlib]System.AsyncCallback callback,
            object 'object'
        ) runtime managed
    {

    } // end of method DoSomething::BeginInvoke

 
    .method public hidebysig newslot virtual
        instance void EndInvoke (
            class [mscorlib]System.IAsyncResult result
        ) runtime managed
    {

    } // end of method DoSomething::EndInvoke

} // end of class delegates.DoSomething


二. 定义了委托,当然是为了使用它,来看下如何使用委托:
在.Net中有三种委托的形式,分别是方法、匿名方法和lambda表达式;我们用方法定义的形式看下委托的使用方法

复制代码 代码如下:


using System;

namespace delegates
{
 public delegate void DoSomething(int times);

    class Program
    {
        static void Main(string[] args)
        {
            //声明委托变量并给委托变量赋值
            DoSomething @do = DoA;
            //可以使用+号或者+=给委托增加方法
            @do += DoB;
            //执行委托时将按照委托的添加顺序先后执行委托中的方法
            @do(1);
            //也可以通过-号或者-= 从委托中移除方法
            @do -= DoA;
            @do(2);

            @do -= DoB;
            //将委托中的所有方法都移除掉之后,委托照样是可以调用的,只是什么都不做
            @do(3);

            Console.Read();
        }
       //定义一个委托相同参数和返回值的方法
        static void DoA(int times)
        {
            Console.WriteLine("Do A {0}", times);
        }

 
        //定义一个委托相同参数和返回值的方法
        static void DoB(int times)
        {
            Console.WriteLine("Do B {0}", times);
        }
    }
}


如上代码中的Main方法,首先我们定义了委托DoSomething的变量@do,并将DoA方法直接赋值给此委托变量;然后我们又使用+=符号或者+号给此委托添加了另一个方法;当然也可以使用-或者-=从委托中去掉方法。
委托比C/C++方法指针强大的地方在于其可以容纳多个方法,也可以执行+/-操作从方法列表中添加或者删除掉方法。
在执行委托加减运算时有几个问题需要我们注意:
1. 委托声明的写法
委托声明时可以用如下写法

复制代码 代码如下:


DoSomething @do = DoA;


这其实是一种简短的写法,我们知道在.Net 1.x中这样写是不允许的只有到.Net 2.0时才允许这么写,在.Net 1.x中必须写成

复制代码 代码如下:


DoSomething @do = new DoSomething(DoA);


我们要在声明时就给@do赋予DoA加上DoB

复制代码 代码如下:


DoSomething @do = DoA + DoB;


这么写是不行的,编译器不干了;必须使用.Net 1.x中的写法

复制代码 代码如下:


DoSomething @do = new DoSomething(DoA) + new DoSomething(DoB);


2. 从委托中减去委托中本不存在的方式时会发生什么呢?
请看如下代码:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjgxgs.html