c# 代理/委託 Delegate

代碼
1. 委託的定義:
委託是函數的封裝,它代表一
""函數.
他們都符合一定的簽名:擁有相同的參數列表,返回值類型.同時,委託也可以看成是對函數的抽象,是函數的
"".此時,委託的實例將代表一個具體的函數.
委託聲明和定義了一個引用類型,它用來封裝方法,用指定的簽名來封裝方法.一個委託的實例,可以封裝靜態或者實例方法.
委託是一種引用的類型,一旦爲委託分配了方法,委託將與該方法完全相同的行爲,委託方法的使用可以像其他任何方法一樣, 具有參數和返回值
    委託的一個特徵是它們的類型是安全的.可以確保被調用的方法簽名是正確的,但他們並不關心調用該方法的是什麼類型的對象,甚至不考慮該方法是靜態方法還是實例方法.(給定委託的實例可以表示任何類型的任何對象上的實例方法或靜態方法,只要方法的簽名匹配於委託的簽名就可以).

2. 委託的使用:
    當要把方法傳遞給其他方法時,需要使用委託.
爲什麼什麼用委託:
        更加靈活的方法調用.

        用於異步回調.

       多線程編程中使用委託來定啓動一個線程時調用的方法.

       C#中的事件模型,用他們來指明處理給定事件的方法.

例:

class Program

{

        
//定義委託

        
delegate double ProcessDelegate(double param1, double param2);

        
static double Multiply(double param1, double param2)

        {

            
return param1 * param2;

        }

        
static double Divide(double param1, double param2)

        {

            
return param1 / param2;

    }

        
static void Main(string[] args)

        {

            
//定義委託變量

            ProcessDelegate pd;

            
double param1 = 20;

            
double param2 = 10;

            Console.WriteLine(
"Enter M to multiply or D to divide");

            
string input = Console.ReadLine();

            
if (input == "M")

            {

                
//初始化委託變量,要把一個函數引用賦給委託變量,

                
//參數是要使用的函數名,且不帶括號.

                pd 
= new ProcessDelegate(Multiply);

            }

            
else

            {

                pd 
= new ProcessDelegate(Divide);

            }

            
//使用該委託調用所選函數

            Console.WriteLine(
"Result: {0}",pd(param1,param2));

            Console.ReadKey();

}

3. 多播委託: 引用多個方法的委託,它連續調用每個方法.


爲了把委託的單個實例合併爲一個多播委託,委託必須是同類型的,返回類型必須是void,不能帶輸出參數out(可以帶引用參數ref).


多播委託應用於事件模型中.


//聲明委託

    
public delegate void myDelegate();

    
public partial class Form1 : Form

    {

        
public Form1()

        {

            InitializeComponent();

        }

        
public void aa()

        {

            Console.WriteLine(
"aa");

        }

        
public void bb()

        {

            Console.WriteLine(
"bb");

        }

        
public void cc()

        {

            Console.WriteLine(
"cc");

        }


        myDelegate md;


        
private void button1_Click(object sender, EventArgs e)

        {

            md 
= new myDelegate(aa);

            md 
+= new myDelegate(bb);

            myDelegate m 
= new myDelegate(cc);

            md 
+= m ;

            md();

        }

    }



4. 異步回調:

由於實例化委託是一個對象,所以可以將其作爲參數進行傳遞.也可以將其賦值給屬性.這樣,方法便可以將一個委託作爲參數來接受,並且以後可以調用該委託.這樣稱爲異步回調,是在較長的進程完成後用來通知調用方的常用方法.以這種方式使用委託時,使用委託的代碼無需瞭解有關所用方法的實現方面的任何信息.


回調的另一個常見用法是定義自定義的比較方法並將該委託傳遞給排序方法.


    例:

//定義委託

    
delegate void Del(int a,int b);

    
class Program

    {

        
static void Main(string[] args)

        {

            Program p 
= new Program();

            Del d 
= new Del(p.F_min);   //實例化委託並傳給他比較的方法.

            p.CallBack(
1030, d);   //調用回調函數

        }


        
//回調函數,將委託實例作爲方法參數進行傳遞.

   
public void CallBack(int a,int b,Del d)

       {

           d(a, b); 
//執行委託

        }

       
//輸出較大的數

        
public void F_max(int a, int b)

        {

            Console.WriteLine(
"大的那個數爲: " + Math.Max(a,b));       

        }
//輸出較小的數

      }

5. 匿名方法

    匿名方法允許我們以一種”內聯”的方式來編寫方法代碼,將代碼直接與委託實例相關聯,從而使得委託實例化的工作更加直觀和方便.

使用例子:

class Program{

    
//定義委託

    
public delegate string dTest(string val);

    
static void Main(string[] args){

        
string mid = "男子足球隊";

        
//匿名方法

        dTest aDelegate 
= delegate(string param){

            param 
+= mid;

            param 
+= "加油.";

            
return param;

        };

        Console.WriteLine(aDelegate(
"中國"));

        Console.ReadLine();

    }

}

如果委託類型的返回類型爲void,匿名方法裏便不能返回任何值.如果不爲void,匿名方法裏返回的值必須和委託類型的返回值兼容.

6. 何時使用委託,何時接口?

   委託:

    當使用事件設計模式時.

    當封裝靜態方法可取時.

    當調用方不需要訪問實現該方法的對象中的其他屬性方法或接口時.

    需要方便的組合.

    當類可能需要該方法的多個實現時.

   接口:

    當存在一組可能被調用的相關方法時.

    當類只需要方法的單個實現時.

    當使用接口的類想要將該接口強制轉換爲其他接口或類類型時.


        
public void F_min(int a, int b)

        {

            Console.WriteLine(
"小的那個數爲: " +Math.Min(a,b));

        }

 

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