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:此文章是本人蔘考網上內容加上自己的理解整合而成,如無意中侵犯了您的權益,請與本人聯繫。

 

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章