快速理解C#高級概念(一) Delegate委托


做.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  博主以及同事和你共同探討感興趣的話題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM