做.NET開發很久,最近重新溫習《C#進階編程》一書。發現很多曾經似懂非懂的問題,其實也是能夠慢慢鑽研慢慢理解的。
所以,打算開寫《C#進階編程系列》博文。其中會借鑒《C#進階編程》一書的概念,也會參照其他高手的博文,希望大家諒解。有不對的地方,歡迎指正。
(另:本博文不會講解定義,文法方面的基礎知識。)
下面如題,我們來講委託。
Delegate委託,在.NET中應用的非常廣泛。會涉及到Lambda運算式,事件,匿名方法等(請關注後續博文)。
那麼何為委託?
通
俗的來講,委託除了必須指定delegate關鍵字和沒有方法實體之外,和指定方法沒有更多區別。你可以當它是一個預留位置,比如你在寫代碼的時候並不知道
你將要處理的是什麼。你只需要知道你將要引入的參數類型和輸出類型是什麼並定義它即可。這就是書本上所傳達的方法簽名必須相同的意思。
下面我們來定義一個基本的委託:
public class Test { //定義委託 public delegate void D_Math(int a, int b); public void Add(int a, int b) { Console.WriteLine("Add方法結果:{0}", a + b); } public void Cut(int a, int b) { Console.WriteLine("Cut方法結果:{0}", a - b); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Test t = new Test(); Test.D_Math D = new Test.D_Math(t.Add);//委託執行個體化,也可Test.D_Math D =t.Add; D += t.Cut;//委託可以以隊列方式執行多個方法,以+=運算子或者-=來增加或者取消隊列中的方法 D(5, 6); } }
執行結果:
以上看出來委託實用的地方了嗎?即委託可以執行任何引入參數類型相同且傳回型別相同的方法,甚至可以執行簽名相同的方法隊列。
那麼我們的方法簽名(即引入參數和輸出參數)真的必須與委託完全一致嗎?答:不是的,我們不能忽略協變與逆變。
我們這裡簡單介紹一下協變與逆變的知識。
“協變”是指能夠使用與原始指定的衍生類別型相比,派生程度更大的類型。
“逆變”則是指能夠使用派生程度更小的類型。
那麼,我們的委託也是接受協變與逆變的。
意思是,如果定義一個delegate,那麼不僅僅簽名完全相同的方法可以賦值給delegate變數。
如果一個方法的參數表符合delegate聲明,但返回的類型是(delegate聲明傳回型別)的衍生類別,那也可以將這個方法賦值給這個delegate變數。
如果一個方法的傳回型別符合delegate的聲明,但參數是(delegate聲明參數類型)的祖先類,那也可以將這個方法賦值給這個delegate變數。
如果一個方法的參數和傳回型別都符合上面兩行的假設,那也可以將這個方法賦值給這個delegate變數。
以下以兩個簡單樣本解釋協變與逆變:
協變:
public class A { } public class B:A { }//B繼承自A public class Test { //定義委託 public delegate A D_Math(); public B Add() { return new B(); } public A Add2() { return new A(); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Test.D_Math d = new Test.D_Math(new Test().Add);//委託返回A,而Add方法返回B,此為協變。 } }
逆變:
public class A { } public class B:A { }//B繼承自A public class Test { //定義委託 public delegate void D_Math(B b); public void Add(B b) { } public void Add2(A a) { } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Test.D_Math d = new Test.D_Math(new Test().Add2);//委託引入參數B,而Add方法參數為A類型,此為協逆變。 } }
以上是本篇對於委託的講解,歡迎大家補充與修正。
更多WEB開發技術請加群:Asp.Net進階群 號碼:261882616 博主以及同事和你共同探討感興趣的話題。