【學習筆記】C#中的委托(delegate)


  Delegate

一、什么是委托?

  委托是一種引用類型,它是函數指針的托管版本。在C#中,委托是一種可以把引用存儲為函數的類型。委托可以引用實例和靜態方法,而函數指針只能引用靜態方法。委托的聲明非常類似於函數,和函數不同的的是委托不帶函數體,並且需要Delegate關鍵字。委托的聲明指定了一個函數簽名,其中包含參數列表和和一個返回類型。在定義了委托后,就可以聲明該委托類型的變量,然后可以將這個變量初始化為與該委托有相同簽名的函數進行引用,隨后可以使用委托變量調用該函數。(ps:其實委托他丫的就是一個類,他的目的就是將方法可以作為其他方法的參數傳遞!)

  委托雖然與函數指針非常相似,但卻不是指針。許多人把.NET中的委托理解為安全的函數指針,這是比較牽強的,委托實現的功能和函數指針非常類似的一點就是提供了程序回調機制。

二、委托四部曲:1、聲明委托類型

            2、有一個方法包含了執行的代碼

            3、創建委托實例

            4、調用委托實例

三、例子:(1)

using System;

namespace ConsoleApp
{
    class Program
    {
        //1、聲明委托類型
        public delegate void AddDelete(int a, int b);
        //2、有一個方法包含了執行的代碼
        public static void Add(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        static void Main(string[] args)
        {
            //3、創建委托實例,使用了new 關鍵字,說明委托也是類,將方法名Add作為參數綁定到該委托實例             
            var adddelete = new AddDelete(Add);
            //4、調用委托實例             
            adddelete(1, 2);
            Console.ReadKey();
        }
    }
}

  (2)使用匿名方法,如下,可以看到這樣就不需要再定義一個Add函數了,

using System;

namespace ConsoleApp
{
    class Program
    {
        public delegate void AddDelete(int a, int b);

        static void Main(string[] args)
        {
            AddDelete adddelete = delegate(int a, int b) { Console.WriteLine(a + b); };
            adddelete(1,2);
            Console.ReadLine();
        }
    }
}

四、C#中被委托的方法必須是靜態的嗎?

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public delegate void AddDelete(int a, int b);
        private class MyClass
        {
            public void Add(int a, int b)
            {
                Console.WriteLine(a + b);
            }
        }
        
        static void Main(string[] args)
        {
            MyClass myClass=new MyClass();          
            var adddelete = new AddDelete(myClass.Add);             
            adddelete(1, 2);
            Console.ReadKey();
        }
    }
}

 

  通過上面的代碼可以看出,委托既可以綁定靜態方法也可以綁定實例方法。但是在綁定實例方法的時候,delegate的target屬性就被設置為指向這個實例方法所屬類型的一個實例對象。當綁定靜態方法時,delegate的target屬性就給NULL

 

 五、什么是多播委托?

  每個委托都只包含一個方法調用,調用委托的次數與調用方法的次數相同。如果要調用多個方法,就需要多次顯示調用這個委托。當然委托也可以包含多個方法,這種委托成為多播委托

    調用過程中:1、多播委托包含一個以上方法的引用且必須是同類型的

          2、多播委托包含的方法必須返回void,否則會拋出run-time exception,並且不能帶參數(但可以帶引用參數)

    例子

using System;

namespace ConsoleApp
{
    public delegate int MyDel(int name);
    class Program
    {
        static int Add1(int a)
        {
            var b = 10 + a;
            Console.WriteLine(b);
            return b;
        }
        static int Add2(int a)
        {
            var b = 10 - a;
            Console.WriteLine(b);
            return b;
        }
        static void Main(string[] args)
        {
            var add = new MyDel(Add1);
            add += new MyDel(Add2);
            Console.WriteLine(add(10));
            Console.ReadKey();
        }
    }
}

也許,你看到這一段代碼時,你會奇怪,+=不會給delegatesand重新賦值嗎?

但是我想說你的擔心是多余的,+=運算符,在我們之前的理解中,它具有賦值的作用,可這里為什么會與上邊的代碼 效果一樣,與你的想象不一致,其實,這里的+=運算符被重載了 ,不再是我們一般理解的:

    int a=0,b=1;
   a+=b;//此時,a變成了 1
} 

在使用委托時,+=將會被重載,它的作用變成了 在不影響已賦值委托變量的前提下,為已賦值的委托變量再次添加一個引用委托方法
 也就是說,每使用一次 +=運算符,委托變量就會被加入一個委托方法,比如原來 委托變量被賦值了,使用一次+=運算符后,委托變量也就同時作為兩個 委托方法的委托了 ,而且,它們運行的先后順序與添加的先后順序一致。

 

 

ps:此文章是本人參考網上內容加上自己的理解整合而成,如無意中侵犯了您的權益,請與本人聯系。

 

  


免責聲明!

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



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