程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> C#委托的本質和委托鏈

C#委托的本質和委托鏈

編輯:C#基礎知識

委托是C#最重要的特性之一,C#後面的所有特性基本都是建立在委托的基礎上的。

1、C#委托是什麼?

可以把C#的委托理解為函數的一個包裝,它使得C#中的函數可以作為參數來被傳遞。如果你學過C++,可以理解為相當於上面的函數指針。

委托的定義和方法的定義類似,只是在定義的前面多了一個delegate關鍵字。下面就是一個委托的例子:

public delegate void MyDelegate(int para1,string para2);

委托能包裝的方法是有一定限制的,例如能被前面的委托類型MyDelegate包裝的方法需要滿足以下條件:

(1)方法的返回類型必須為void;

(2)方法必須有兩個參數,並且第一個參數應為int類型,第二個參數為String類型。

比如:public vodi MyMethod(int a,string b){}

總結一下可以得出:被委托包裝的方法必須滿足方法的簽名必須與委托一致,並且返回類型也是要一致的。(方法簽名:包括參數的個數、類型和順序;返回類型不包含在放哪廣發簽名裡)。

 

2、委托的使用

使用的方式當然是Show出代碼來解釋最清楚了。

class Program
{
  //1、使用delegate關鍵字來定義一個委托類型
  delegate void MyDelegate(int para1,int para2);
  static void Main(string[] args)
  {
    /2、聲明委托變量d
    MyDelegate d;

    //3、實例化委托類型,傳遞的方法也可以為靜態方法,這裡傳遞的是實例方法
    d=new MyDelegate(new Program().Add);

    //4、委托類型作為參數傳遞給另一個方法
    MyMethod(d);
    Console.ReadKey();
  }

  //該方法的定義必須與委托定義相同,即返回類型為void,兩個int類型的參數
  void Add(int para1,int para2)
  {
    int sum=para1+para2;
    Console.WriteLine("兩個數的和為:"+sum);
  }

  //方法的參數是委托類型
  Private static void MyMethod(MyDelegate mydelegate)
  {
    //5、在方法中調用委托
    mydelegate(1,2);
  }
}

從上面的代碼可以得出委托使用的步驟:定義委托類型->聲明委托變量->實例化委托->作為參數傳遞給方法->調用委托。

 

3、為什麼要引入委托?

委托最大的作用,就是使得一個方法可以作為另一個方法的參數進行傳遞。

比如我們要實現一個打招呼的方法,但每個國家打招呼的方式是不一樣的,我們可能會使用switch的方式進行設計,但這樣做明顯導致可擴展性不足,每次增加一個新的打招呼方法都必須去修改case語句來適應新的需求。如果有了委托,情況就不一樣了:

class Program
{
  //定義委托類型
  public delegate void GreetingDelegate(string name);
  static void Main(string[] args)
  {
    //引入委托之後
    Program p=new Program();
    p.Greeting("李志",p.ChineseGreeting);
    p.Greeting("Tommy Li",p.EnglishGreeting);
    Console.ReadKey();
  }

  public void Greeting(string name,GreetingDelegate callback)
  {
    callback(name);
  }

  public void ChineseGreeting(string name)
  {
    Console.WriteLine("你好,"+name);
  }

  public void EnglishGreeting(string name)
  {
    Console.WriteLine("Hello,"+name);
  }
}

在引入委托之後,就可以把函數作為參數傳遞給另一個方法了。委托可以提高方法的可擴展性。

 

4、委托的本質

委托是一個類類型,從哪裡看得出來呢,就需要從IL代碼中找到答案。

C#代碼如下:

class Program
{
  public delegate void DelegateTest(int param);
  static void Main(string[] args)
  {
  }
}

 

從上圖中便可以得出委托DelegateTest是一個類,繼承自System.MulticastDelegate類型。並且該類包含了一個構造函數和3個方法。有了構造函數,我們才能使用new關鍵字來實例化委托類型。而Invoke方法則用來顯式地調用委托。此外,BeginInvoke和EndInvoke是兩個異步方法(以後解釋什麼叫做異步方法)。

在最開篇開始的代碼當中,我們使用mydelegate(1,2)來調用方法,這是隱式調用,其背後也是要通過調用Invoke方法來調用委托的。當時,我們使用顯式調用mydelegate.Invoke(1,2)也行。

 

5、委托鏈

C#中的委托同樣可以封裝多個方法。C#中把封裝多個方法的委托稱作委托鏈或多路廣播委托。

可以通過“+=”運算符,將多個委托對象鏈接到一個委托對象實例上,成為多路廣播委托實例。也可以使用“-=”運算符將某個委托從委托鏈對象上移除。

class Program
{
  //聲明一個委托類型
  public delegate void DelegateTest();
  static void Main(string[] args)
  {
    //用靜態方法來實例化委托
    DelegateTest dtstatic =new DelegateTest(Program.Method1);
    DelegateTest dtinstance=new DelegateTest(new Program().Method2);

    //定義一個委托對象,一開始初始化為null,即不代表任何方法
    DelegateTest delegatechain=null;

    //使用“+”符號鏈接委托,鏈接多個委托後就成為了委托鏈
    delegatechain+=dtstatic;
    delegatechain+=dtinstance;


    //delegatechain-=dtinstance;
    //調用委托鏈
    delegatechain();
    Console.Read();
  }

  private static vodid Method1()
  {
    Console.WriteLine("這是靜態方法");
  }

  private void Method2()
  {
    Console.WriteLine("這是實例方法");
  }
}

總結:委托,是C#中一個最基本最重要的特性。大家可以借助反編譯工具好好看一下委托的IL代碼。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved