C# 委託和事件

1、是什麼編程

1)委託包含對方法而不是方法名稱的引用。使用委託能夠在運行時動態設定要調用的方法,不知道方法名稱,也能夠調用方法,執行(或調用)一個委託將執行該委託引用的方法。ide

2)委託將名稱與方法的定義鏈接起來,即將方法的實現附加到該名稱。這樣即可以使用該名稱調用特定的方法。可是,委託要求方法的實現和委託必須具備相同的方法簽名(也就是說,他們應該具備相同數量/類型的參數),並有相同類型的返回值。函數

3)委託更像一個具備通用的方法名稱,在不一樣的狀況將該名稱指向不一樣的方法,並經過委託執行這些方法。this

2、怎麼用spa

使用委託包括三個步驟:.net

1)定義委託線程

2)實例化委託指針

3)使用委託code

咱們上一個例子:orm

class Program  
{  
    //定義一個委託  
    public delegate int Call(int num1, int num2);  
  
    class Math  
    {  
        public int Mutiply(int num1, int num2)  
        {  
            return num1 * num2;  
        }  
  
        public int Divide(int num1, int num2)  
        {  
            return num1 / num2;  
        }  
    }  
  
    static void Main(string[] args)  
    {  
        Call objCall;  
        Math objMath = new Math();  
        objCall = new Call(objMath.Mutiply);//實例化一個委託  
        
        int result = objCall(5, 3);//使用委託  
        Console.WriteLine("結果爲 {0}", result);  
    }  
}  

值得說明是,

objCall = new Call(objMath.Mutiply);//實例化一個委託  

objCall = objMath.Mutiply; //直接給委託賦值

這兩種方式效果是同樣的,只是兩種不一樣的寫法。用.net reflector反編譯上述代碼,會發現其實objCall = objMath.Mutiply最終仍是會編譯生成objCall = new Call(objMath.Mutiply)。

 上面的例子,咱們再進一步,用匿名委託實現:

static void Main(string[] args)  
{  
    Call objCall = delegate(int num1, int num2) { return num1 * num2; };//匿名委託  
    int result = objCall.Invoke(3, 5);//使用委託  
    Console.WriteLine("結果爲 {0}", result);//輸出:結果爲 15  
}  

咱們還能夠將:

int result = objCall.Invoke(3, 5);//使用委託  

替換爲:

int result = objCall(3, 5);//使用委託  

效果是同樣的。

 再進一步,用Lambda表達式進行簡化,能夠將:

Call objCall = delegate(int num1, int num2) { return num1 * num2; };//匿名委託  

替換爲:

Call objCall = (int num1, int num2) => { return num1 * num2; };//Lambda表達式  

更簡化一步,變爲:

Call objCall = (num1, num2) => { return num1 * num2; };//Lambda表達式  

這就是C#委託的進化過程以及C#Lambda表達式對委託的支持。

 3、何時用

1)委託相似於C語言中的函數指針,能夠將方法做爲函數的參數進行傳遞

2)當不知道方法的具體實現時,就能夠定義個委託,讓它替咱們幹活

3)咱們在編程時用的最多的就是事件註冊時使用。

好比:

this.button1.Click += new EventHandler(button1_Click);//button1註冊Click事件 
private void button1_Click(object sender, EventArgs e)  
{  
    //方法具體實現內容  
}  

能夠看到方法button1_Click做爲參數傳遞給了EventHandler委託。

再好比在線程方法中:

Thread th = new Thread(new ThreadStart(Method));//這裏的ThreadStart就是一個委託,裏面能夠直接傳一個方法名Method,以委託的形式調用方法  
th.IsBackground = true;  
th.Start();  

 4、典型應用

好比兩個窗體Form1(一個文本框,一個按鈕)、Form2(一個文本框,一個按鈕)之間進行傳值,Form1到Form2能夠經過構造函數傳值,但若是要將Form2的值傳回給Form1該怎麼辦呢?這裏就能夠用到委託,這也是委託的經典應用場景之一。

 Form1.cs部分代碼:

 private void button1_Click(object sender, EventArgs e)
 {
     Form2 form2 = new Form2();
     //經過public變量傳值
     form2.text = this.textBox1.Text;
     //經過委託將子窗體的值傳回主窗體
     form2.delegateShow = form2_ShowDelegateEventHandler;
     //經過註冊事件將子窗體的值傳回主窗體
     form2.ShowDelegateEventHandler += new Form2.ShowDelegate(form2_ShowDelegateEventHandler);
     form2.Show();
 }

 void form2_ShowDelegateEventHandler(string text)
 {
     this.textBox1.Text = text;
 }

 Form2.cs部分代碼:

public delegate void ShowDelegate(string text);//聲明委託
public event ShowDelegate ShowDelegateEventHandler;//聲明事件

public string text;//public變量
public ShowDelegate delegateShow;//public委託變量

private void Form2_Load(object sender, EventArgs e)
{
    this.textBox1.Text = text;
}

private void button1_Click(object sender, EventArgs e)
{
    //寫法1:用事件
    if (ShowDelegateEventHandler != null)
        ShowDelegateEventHandler(this.textBox1.Text);

    //寫法2:用委託
    delegateShow(this.textBox1.Text);
    this.Close();
}

 5、總結

1)委託是方法的簽名,能夠將委託做爲方法的參數進行傳遞

2)事件基於委託,或者說事件是特殊的委託

3)委託能夠用匿名委託簡化代碼(不須要再聲明委託,而後實現),還能夠用Lambda表達式進一步簡化匿名委託(這也是C#推薦的方式)。

 

代碼下載:https://files.cnblogs.com/files/guwei4037/委託和事件窗體傳值.zip

相關文章
相關標籤/搜索