解析.Net 4.0 中委託delegate的使用詳解_實用技巧

來源:互聯網
上載者:User
.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. 從委託中減去委託中本不存在的方式時會發生什麼呢?
請看如下代碼:
複製代碼 代碼如下:

DoSomething @do = DoA;
@do -= DoB;

第一行代碼我生命了@do並將DoA賦予它;第二行代碼我嘗試從@do中減去DoB,DoB並沒有在@do的方法列表中存在,這樣會發生什麼情況呢?首先編譯器沒有報錯,程式可以正常的編譯;執行代碼發現可以程式可以正常執行,調用@do委託時正確的執行了DoA方法;這說明了.Net包容了我們程式員犯的錯,我們從委託變數中減去一個委託中並不包含的方法時,不會報錯會正常的執行。
3. 對委託做減法,所有委託都減完了,會怎樣呢?看如下代碼
複製代碼 代碼如下:

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

這樣的代碼可以成功編譯,但是在運行時會報NullReferenceException;這顯然不是我們希望的,所以對委託做減法時要特別注意。
複製代碼 代碼如下:

<span style="text-decoration: line-through;">public delegate void DoIt(string task);

class Test
{
    static void Main(string[] args)
    {
        //DoIt聲明,賦予一個參數更寬泛的方法是合法的
        DoIt doIt = new DoIt(DoItImpl);
        doIt("hello");
    }

    //比委託定義中的參數更寬泛,string類型可以隱式轉換成object
    static void DoItImpl(object task)
    {
        Console.WriteLine("DoItImpl {0}",task);
    }
}
</span>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.