1. 委派語法#
- 委派 (Delegate) 類似於 C/C++ 中的函式指針,是可存有對某個方法的引用的一種引用類型變數。
- 宣告語法:
delegate <return type> <delegate-name> <parameter list>
// 宣告一個委派,裝載 void function(string)
public delegate void PrintString(string text);
public static void Main(string[] args)
{
// 新增一個委派事件,指向 ToUpperCase
PrintString e = new PrintString(ToUpperCase);
string text = "Hello World!";
e.Invoke(text);
// HELLO WORLD!
// 將另一個事件加到委派中,指向 ToLowerCase
e += ToLowerCase;
e.Invoke(text);
// HELLO WORLD!
// hello world!
// 將委派中的 ToUpperCase 取消掉
e -= ToUpperCase;
e.Invoke(text);
// hello world!
}
public static void ToUpperCase(string text) {
Console.WriteLine(text.ToUpper());
}
public static void ToLowerCase(string text) => Console.WriteLine(text.ToLower());
2. 簡化事件註冊#
// 定義 EventHandler 為可以接收物件與傳參的委派
public delegate void EventHandler(object sender, EventArgs e);
// 定義傳參可以儲存的內容
public class HandleClickEventArgs : EventArgs
{
public string Message;
}
// 創建一個按鍵並為其創建一個可以註冊事件的委派
public class Button
{
public string name;
public Button(string _name)
{
name = _name;
}
// 在物件內部定義一個委派存放事件
private event EventHandler Click;
public notify()
{
// 執行委派
// Handler.Invoke(this, e);
Handler(this, e);
}
}
// 註冊事件的傳參需與委派的傳參一致
private static void Click(object sender, EventArgs e)
{
Console.WriteLine(
sender.GetType() + " " +
(e as HandleClickEventArgs)?.Message
);
}
public void static Main(string[] args)
{
EventArgs = new HandleClikEventArgs()
{
Message = "is clicked!"
};
Button button = new Button("TV Remote Button");
button.Click += new EventHandler(Click);
button.Click += Click;
button.Click += delegate
{
Console.WriteLine("Check! Check!");
};
button.Click += (sender, e) => Console.WriteLine(
(sender as Button)?.name + " " +
(e as HandleClickEventArgs)?.Message
);
button.notify(e);
// Button is clicked!
// Button is clicked!
// Check! Check!
// TV Remote Button is clicked!
}
- 注意到
Button
內有一個委派被定義為 delegate void function(object sender, EventArgs e)
,並被命名為 Click
,故我們會向它註冊事件。- 在 C#1 中,完整的寫法是:
button.Click += new EventHandler(Click);
- 在 C#2,透過 Method group conversion 可將其簡化成(條件是兩者的傳參要相同):
- 如果方法較簡單也可以透過匿名方法(anonymous method)註冊:
- 需要傳參時:
button.Click += delegate(object sender, EventArgs e) { Console.WriteLine("Click!"); };
- 不需要傳參時:
button.Click += delegate { Console.WriteLine("Click!"); };
- 在 C#3 中,可以透過 Lambda 表達式來創建。
button.Click += (sender, e) => Console.WriteLine("Click!");