曾經對委託和事件非常頭疼,好在現在以自己的方式入門了,就行以自己的方式把它過一遍,當作學習日記吧。
委託(delegate)是一種參考型別,我們在處理他的時候要當作類來看待而不是方法,說白了委託就是對方法或者方法列表的引用,調用一個委託執行個體就好像是調用c++中的指標一樣,他封裝了對制定方法的引用,或者說委託起到的是橋樑的作用,執行個體後的委派物件會將給定的參數傳遞給他所回調的方法,並去執行方法。
看一個簡單的例子:
//聲明一個委託
delegate int myDelegateHandler(int a, int b);
public class A
{
//靜態處理方法
public static int M1(int a, int b)
{
int c = 0;
c = a + b;
return c;
}
}
//入口類
public class B
{
public static void Main()
{
//執行個體一個委託
myDelegateHandler mdh = new myDelegateHandler(A.M1);
//調用委託
int sum = mdh(2, 2);
Console.WriteLine(sum.ToString());
}
}
上面是一個非常簡單的例子,具體的實現步驟:
1、 先聲明個委託執行個體 ;
2、然後提供要處理的方法;
3、再執行個體化委託(把委託看作是類的話,執行個體化委託就不難理解了,其參數是要處理的方法,這裡的方法 不用加括弧,執行個體化的過程就是裝載方法的過程,就好像需要參數的建構函式一樣)執行個體化後的委派物件就好比是c++中的指標,它本身就是封裝了方法的對象;
4、最後我們調用委派物件就好比是調用了被封裝方法本身,調用時的參數也就傳給了被封裝的方法。
5、需要注意的是 所聲明的委託無論是 參數個數,參數類型,傳回值類型 都要和所要封裝的方法保持一致,當調用委託執行個體對象時,所傳入的參數也要保持一致 ,否則會出現錯誤。
委託鏈
我們知道委託是對方法的封裝,而且委託可以封裝很多方法形成委託鏈,其實委託就好像是一個容器,他封裝了我們想要實現的若干方法,當調用委派物件(相當於c++中的指標)時,就會順序的執行它所封裝的所有的方法,如果有傳回值的話,往往返回的是最後一個被執行的方法的傳回值,委託鏈的形成可以用"+="或"-="對不同的委託執行個體進行二元操作。
委託鏈執行個體:
//定義一個委託
public delegate void PrintHandler(string message);
public class PrintProvider1
{
public void Print(string msg)
{
Console.WriteLine( msg + "1111111");
}
}
public class PrintProvider2
{
public void Print(string msg)
{
Console.WriteLine( msg + "2222222");
}
}
class Delegate1
{
public static void StaticPrint(string msg)
{
Console.WriteLine(msg + "3333333");
}
public static void Main()
{
string s = "委託鏈";
PrintProvider1 pp1 = new PrintProvider1();
PrintProvider2 pp2 = new PrintProvider2();
//建立委託執行個體
PrintHandler prn1 = new PrintHandler(pp1 .Print );
PrintHandler prn2 = new PrintHandler(pp2 .Print );
PrintHandler prn3 = new PrintHandler(StaticPrint );
Console.WriteLine("委託執行個體prn1的列印結果");
prn1(s );
Console.WriteLine("委託執行個體prn2的列印結果");
prn2(s);
Console.WriteLine("委託執行個體prn1+prn2的列印結果");
PrintHandler prn = prn1 + prn2;
prn(s);
Console.WriteLine("委託執行個體prn1+prn2+prn3的列印結果");
prn += prn3;
prn(s);
Console.WriteLine("委託執行個體prn1+prn3的列印結果");
prn -= prn2;
prn(s);
Console.WriteLine("委託執行個體prn3的列印結果");
prn -= prn1;
prn(s);
Console.WriteLine("試圖調用null委託會引發異常");
try
{
prn -= prn3;
prn(s);
}
catch (NullReferenceException ex)
{
Console.WriteLine(ex .Message );
}
Console.WriteLine("試圖從null中移出委託是無效操作");
try
{
prn -= prn3;
}
catch (NullReferenceException ex)
{
Console.WriteLine(ex .Message );
}
Console.Read();
}
}
執行結果
委託執行個體prn1的列印結果
委託鏈1111111
委託執行個體prn2的列印結果
委託鏈2222222
委託執行個體prn1+prn2的列印結果
委託鏈1111111
委託鏈2222222
委託執行個體prn1+prn2+prn3的列印結果
委託鏈1111111
委託鏈2222222
委託鏈3333333
委託執行個體prn1+prn3的列印結果
委託鏈1111111
委託鏈3333333
委託執行個體prn3的列印結果
委託鏈3333333
試圖調用null委託會引發異常
未將對象引用設定到對象的執行個體。
試圖從null中移出委託是無效操作