委托是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代碼。