C#中的delegate

pamxy發表於2013-09-10

轉自:http://zhidao.baidu.com/link?url=xyEmK-9RCxUFgUPWbwTDp9kg3cdb-JRCG2V2oTTiPdHIZNI3BihhyGT_94ewNcz5PCvla_l6nsNyk8E5XoRa2a

Delegate類簡介
------------------------      
名稱空間:System
程式集:mscorlib(在 mscorlib.dll 中)

   委託(Delegate)類是一種資料結構,通過它可引用靜態方法或引用類例項及該類的例項方法。 
以往的介面程式設計中我們應該都接觸過各種型別的事件驅動(event driven)的處理模式,
在這種模式裡,我們定義相應事件觸發的函式。
例如:
Button1 的 Click事件,我們可以編寫Button1_Click 或 Btn1Clicked等函式來做相應的驅動處理。
而事件與驅動函式的對應關係就是通過委託(Delegate)類來關聯的。

其實委託(Delegate)類這種資料結構有些類似於之前C/C++中的函式指標。

Delegate類一個簡單應用
------------------------     
1.定義一個Delegate函式資料結構
2.定義Delegate將引用的靜態方法或引用類例項及該類的例項方法
3.Delegate資料變數指向例項方法
4.通過Delegate資料變數執行例項方法

A very basic example (TestClass.cs):

using System;

namespace MySample
{
    class TestClass
    {
    //1.定義一個Delegate函式資料結構
        public delegate void GoDelegate();

        [STAThread]
        static void Main(string[] args)
        {
        //3.Delegate資料變數指向例項方法
            GoDelegate goDelegate = new GoDelegate( MyDelegateFunc);

        //4.通過Delegate資料變數執行例項方法
            goDelegate();
            return;
        }
   
        //2.定義Delegate將引用的靜態方法或引用類例項及該類的例項方法
        public static void MyDelegateFunc()
        {
            Console.WriteLine("delegate function...");
        }        
    }
}

編譯執行結果:

# TestClass.exe
delegate function...

使用Delegate類和Override實現多型的比較
----------------------------------------------- 
1.使用Delegate類的時候,下面的例子可以很清楚的說明。
  1.1 首先定義一個動物基類(MyAnimalDelegateClass), 基類中有顯示屬性的(ShowAnimalType)的public方法。
      並且在ShowAnimalType方法中呼叫Delegate引用的例項方法

  1.2 定義獅子(LionDelegateClass)和馬(HorseDelegateClass)兩個子類。Delegate與各自的例項方法繫結
      實現不同的屬性顯示(ShowAnimalType)方法。

////Delegate example (TestClass.cs):

using System;

namespace MySample
{
   class TestClass
   {
      [STAThread]
      static void Main(string[] args)
      {
      //獅子(LionDelegateClass)的屬性顯示(ShowAnimalType)方法呼叫
         LionDelegateClass lionDelegate = new LionDelegateClass();
         lionDelegate.ShowAnimalType("MySample");

      //馬(HorseDelegateClass)的屬性顯示(ShowAnimalType)方法呼叫
         HorseDelegateClass horseDelegate = new HorseDelegateClass();
         horseDelegate.ShowAnimalType("MySample");
      }
   }

   //動物基類(MyAnimalDelegateClass)
   public class MyAnimalDelegateClass
   {
      //Delegate資料結構定義
      public delegate void DelegateFunction(string strFuncName);

      private DelegateFunction m_delegateFunction = null;

      //Delegate型別的屬性
      public DelegateFunction delegateFunction 
      {
         get 
         {
            return m_delegateFunction;
         } 
         set 
         {
            m_delegateFunction = value;
         }
      }
    
      //屬性顯示(ShowAnimalType)方法
      public void ShowAnimalType(string strFuncName)
      {
         if (delegateFunction != null)
         {
            object[] args = {strFuncName};
         //呼叫Delegate引用的例項方法
            delegateFunction.DynamicInvoke(args);
         }
      }
   }

   //獅子(LionDelegateClass)
   public class LionDelegateClass:MyAnimalDelegateClass
   {
      public LionDelegateClass()
      {
         this.delegateFunction = new DelegateFunction(subFunction1);
      }

      //獅子(LionDelegateClass)例項方法的實裝
      private void subFunction1(string strFuncName)
      {
         System.Console.WriteLine(
            string.Format("[{0}]This is a lion....", strFuncName));
      }
   }

   //馬(HorseDelegateClass)
   public class HorseDelegateClass:MyAnimalDelegateClass
   {
      public HorseDelegateClass()
      {
         this.delegateFunction = new DelegateFunction(subFunction2);
      }

      //馬(HorseDelegateClass)例項方法的實裝
      private void subFunction2(string strFuncName)
      {
         System.Console.WriteLine(
            string.Format("[{0}]This is a horse....", strFuncName));
      }
   }
}

編譯執行結果:

# TestClass.exe

[MySample]This is a lion....
[MySample]This is a horse....

2.使用Override實裝的時候,參考下面的例子。
  1.1 首先定義一個動物基類(AbstractAnimalNoDelegateClass), 基類中有顯示屬性的(ShowAnimalType)的public方法。
      並且在ShowAnimalType方法中呼叫抽象方法(NoDelegateFunction)

  1.2 定義獅子(LionNoDelegateClass)和馬(HorseNoDelegateClass)兩個子類。
      子類中實裝抽象方法(NoDelegateFunction)
      實現不同的屬性顯示(ShowAnimalType)方法。

////Override example (TestClass.cs):

using System;

namespace MySample
{
   class TestClass
   {
      [STAThread]
      static void Main(string[] args)
      {
          //獅子(LionNoDelegateClass )的屬性顯示(ShowAnimalType)方法呼叫
          LionNoDelegateClass lionNoDelegate = new LionNoDelegateClass();
       lionNoDelegate.ShowAnimalType("MySample");

          //馬(HorseNoDelegateClass )的屬性顯示(ShowAnimalType)方法呼叫
       HorseNoDelegateClass horseNoDelegate = new HorseNoDelegateClass();
       horseNoDelegate.ShowAnimalType("MySample");
      }
   }

   //動物基類(AbstractAnimalNoDelegateClass)
    public abstract class AbstractAnimalNoDelegateClass
    {
        public void ShowAnimalType(string strFuncName)
        {
            //抽象方法(NoDelegateFunction)呼叫
            NoDelegateFunction(strFuncName);
        }
        //在基類中定義抽象方法(NoDelegateFunction)
        protected abstract void NoDelegateFunction(string strFuncName);
    }

    //獅子(LionNoDelegateClass )
    public class LionNoDelegateClass:AbstractAnimalNoDelegateClass
    {
    // 子類中實裝抽象方法(NoDelegateFunction)
        protected override void NoDelegateFunction(string strFuncName)
        {
            System.Console.WriteLine(
                string.Format("[{0}]This is a lion....", strFuncName));
        }
    }
    
   //馬(HorseNoDelegateClass )
    public class HorseNoDelegateClass:AbstractAnimalNoDelegateClass
    {
    // 子類中實裝抽象方法(NoDelegateFunction)
        protected override void NoDelegateFunction(string strFuncName)
        {
            System.Console.WriteLine(
                string.Format("[{0}]This is a horse....", strFuncName));
        }
    }
}

編譯執行結果:

# TestClass.exe

[MySample]This is a lion....
[MySample]This is a horse....

3.比較Delegate和Override實裝方式
  可以看出Delegate實裝方式中,相當於定義一個函式指標成員變數。
  通過把實裝函式的地址賦給該成員變數,實現同樣的方法,處理方式的不同。
  而Override方式中,則是在父類中預先定義好介面,通過實裝的不同,
  來實現同樣的方法,處理方式的不同。
  Delegate實裝方式比較靈活,適合設計不是很完善的場合,便於修改。
  Override方式封裝性好,相對比較安全。

MulticastDelegate 類的應用
---------------------------------
 在C#中,委託(Delegate)類是多路委託,這就說可以同時指向多個處理函式,
並且可以按照委託的先後順序,執行相應的函式。
     
如下例:
using System;

namespace MySample
{
    class TestClass
    {
        [STAThread]
        static void Main(string[] args)
        {
            DogDelegateClass dogDelegate = new DogDelegateClass();
            dogDelegate.ShowAnimalType("MySample");

    }

    public class MyAnimalDelegateClass
    {
        public delegate void DelegateFunction(string strFuncName);

        private DelegateFunction m_delegateFunction = null;

        public DelegateFunction delegateFunction 
        {
            get 
            {
                return m_delegateFunction;
            } 
            set 
            {
                m_delegateFunction = value;
            }
        }

        public void ShowAnimalType(string strFuncName)
        {
            if (delegateFunction != null)
            {
                object[] args = {strFuncName};

                delegateFunction.DynamicInvoke(args);
            }
        }
    }

    public class DogDelegateClass:MyAnimalDelegateClass
    {
        public DogDelegateClass()
        {
      //多路委託函式 設定
            this.delegateFunction =  new DelegateFunction(subFunction31);
            this.delegateFunction += new DelegateFunction(subFunction32);
        }
  //委託函式1
        private void subFunction31(string strFuncName)
        {
            System.Console.WriteLine(
                string.Format("[{0}]This is a dog....", strFuncName));
        }
  //委託函式2
        private void subFunction32(string strFuncName)
        {
            System.Console.WriteLine(
                string.Format("[{0}]This is a nice dog....", strFuncName));
        }
    }
}

編譯執行結果:

# TestClass.exe

[MySample]This is a dog....
[MySample]This is a nice dog....

相關文章