加入 Form1_Load事件
1: delegate int multiply(int x, int y);
2: delegate int timestwo(int x); // [1] 新增一個叫做timestwo的delegate,其輸入個數 = 1, 輸出個數=1
3: 4: timestwo t = delegate(int x) { return 2 * x; }; // 定義一個timestwo變數t, 利用匿名方法初始化之
5: multiply m = delegate(int x, int y) { return x * y; };
6: private void button2_Click(object sender, EventArgs e)
7: { 8: MessageBox.Show(t(5).ToString()); 9: MessageBox.Show( m(5, 6).ToString()); 10: }[重點1]
常見匿名方法(Anonymous Methods)是將程式碼區塊(code block)當做委派(delegate)參數傳遞的一種方式
匿名方法: delegate( arg1, arg2){ … }
以Button為例:
button物件.事件名稱 += delegate( 引數1, 引數2)
{
.............(code block)...........
};
下面為Click和MouseWheel委派事件
1: private void Form1_Load(object sender, EventArgs e)
2: {3: button1.Click += delegate(System.Object o, System.EventArgs ea)
4: {5: MessageBox.Show("訊息1:Click");
6: };7: button1.MouseWheel += delegate(System.Object o, System.Windows.Forms.MouseEventArgs ms)
8: {9: string str = ms.Delta > 0 ? "滾輪>0" : "滾輪<0";
10: MessageBox.Show("訊息2:MouseWheel" + str);
11: }; 12: 13: }在撰寫Click事件前, 先了解匿名函式需委派傳入哪些參數???
step1.
反白Click並按右鍵, 接著點選移至定義
step2.
繼續點選EventHandler按右鍵, 接著點選移至定義
step3.
可以追蹤到EventHandler的定義
1: namespace System
2: {3: // 摘要:
4: // 代表處理不含事件資料之事件的方法。
5: //
6: // 參數:
7: // sender:
8: // 事件的來源。
9: //
10: // e:
11: // 未包含任何事件資料的 System.EventArgs。
12: [Serializable]13: [ComVisible(true)]
14: public delegate void EventHandler(object sender, EventArgs e);
15: }其中EventHandler引數的部分主要有兩個object(哪個物件觸發)和EventArgs(事件種類)
step4.
因此, 上面button1的Click Event可以定義如下:
1: button1.Click += delegate(System.Object o, System.EventArgs ea)
2: { 3: ... 4: }===================================================================================================
step5.
依樣畫葫蘆, 我們也可以追蹤MouseWheel事件該如何定義delegate function
反白MouseWheel並按右鍵, 接著點選移至定義
step6.
同上一個步驟, 反白MouseEventHandler, 並按右鍵並選擇<移至定義>,
1: //
2: // 摘要:
3: // 發生於控制項擁有焦點,且移動滑鼠滾輪時。
4: [EditorBrowsable(EditorBrowsableState.Advanced)]5: [SRDescription("ControlOnMouseWheelDescr")]
6: [Browsable(false)]
7: [SRCategory("CatMouse")]
8: public event MouseEventHandler MouseWheel;
step7.
可以追蹤到MouseEventHandler的delegate function需要兩的引數object和MouseEventArgs
1: namespace System.Windows.Forms
2: {3: // 摘要:
4: // 表示處理表單、控制項或其他元件之 MouseDown、MouseUp 或 MouseMove 的方法。
5: //
6: // 參數:
7: // sender:
8: // 事件的來源。
9: //
10: // e:
11: // 包含事件資料的 System.Windows.Forms.MouseEventArgs。
12: public delegate void MouseEventHandler(object sender, MouseEventArgs e);
13: }step8.
因此, 上面button1的MouseWheel Event可以定義如下
1: button1.MouseWheel += delegate(System.Object o, System.Windows.Forms.MouseEventArgs ms)
2: { 3: ... 4: }---------------------------------------------------------------------------------------------------------------------------------------------------------
[重點2]
(1) 宣告語法: delegate output argument 委派名稱(input arguments)
output argument: 可以為void, 或 int, double,…等
input argument: 例如可以為一個整數輸入 (int x), 兩個雙精準度輸入 (double x, double y)…等
(2) 利用匿名方法初始化 委派物件, PS.匿名方法的輸入輸出個數必須和宣告時相同
下面定義兩個委派函式(delegate function), 分別為 multiply和timestwo, 前者兩個輸入引數, 後者一個輸入引數
第4,5行分別匿名方法初始化timestwo和multiply物件(t, m)
1: delegate int multiply(int x, int y);
2: delegate int timestwo(int x); // [1] 新增一個叫做timestwo的delegate,其輸入個數 = 1, 輸出個數=1
3: 4: timestwo t = delegate(int x) { return 2 * x; }; // 定義一個timestwo變數t, 利用匿名方法初始化之
5: multiply m = delegate(int x, int y) { return x * y; };
6: private void button2_Click(object sender, EventArgs e)
7: { 8: MessageBox.Show(t(5).ToString()); 9: MessageBox.Show( m(5, 6).ToString()); 10: }[重點3]
delegate型別物件s1和s2, 分別用不同的匿名函式實作(初始化)之,
利用產生隨機亂數, 若>0.5 回傳字串s1 字串"Hello world!" 否則回傳s2 字串"It's me, Ryan!"
1: delegate string sayHi(); // [2] 新增一個叫做sayHi的delegate,其輸入個數 = 0, 輸出個數=1
2: sayHi s1 = delegate() { return "Hello world!"; }; // 定義一個SayHi變數s1, 利用匿名方法初始化之
3: sayHi s2 = delegate() { return "It's me, Ryan!"; };
4: private void button3_Click(object sender, EventArgs e)
5: {6: Random c = new Random();
7: double x = c.NextDouble();
8: string str = x > 0.5 ? s1() : s2();
9: MessageBox.Show(x.ToString() + str); 10: }-------------------------------------------------------------------------------------------------------------------------------------------------------
[重點4]另一種常見的應用: 在定義執行緒的副程式上
以下為ThreadStart的 delegate function定義: 無輸入引數狀況
1: public delegate void ThreadStart();
1: private void button4_Click(object sender, EventArgs e)
2: { 3: 4: Thread th = new Thread(
5: delegate() // 匿名方法: 輸入/輸出個數=0
6: {7: while (true)
8: {9: System.Console.Write("Hello, ");
10: System.Console.WriteLine("World!");
11: } 12: } 13: 14: ); 15: th.Start(); 16: }一個輸入引述狀況
1: public delegate void ParameterizedThreadStart(object obj);
測試如下
1: private void button7_Click(object sender, EventArgs e)
2: {3: Thread th = new Thread(DoJob);
4: int x = 5;
5: 6: th.Start(x); 7: }8: public static void DoJob(object data)
9: { 10: 11: while(true)
12: {13: Console.WriteLine("Static Thread procedure.Data = '{0}''",data);
14: } 15: }將Thread結果顯示在人機介面上, 必須利用Invoke這個指令
1: Thread th = new Thread(delegate() // 匿名函式
2: {3: int cnt = 0;
4: while (true)
5: { 6: cnt++;7: this.Invoke( // 將程式碼交給主線程執行
8: (MethodInvoker)delegate() //使用匿名方法
9: { 10: label1.Text = cnt.ToString(); 11: }12: ); //Invoke
13: } 14: 15: }); 16: th.Start();-------------------------------------------------------------------------------------------------------------------------------------------------------
[重點5]
delegate 可以與具名方法(Named Methods)或是匿名方法(Anonymous Methods)產生關聯
以下範例利用addSomething具名方法來實體化匿名方法addNumber物件a
1: delegate int addNumber(int x);
2: // Define a named method:
3: static int addSomething(int x) { return x + 2; }
4: private void button6_Click(object sender, EventArgs e)
5: {6: // 具名方法
7: addNumber a = addSomething; 8: 9: MessageBox.Show( a(5).ToString() ); 10: 11: // 匿名方法
12: a = delegate(int x) { return 2 * x; };
13: MessageBox.Show(a(5).ToString()); 14: }-------------------------------------------------------------------------------------------------------------------------------------------------------
(1) 利用匿名方法(Anonymous Methods)初始化delegate物件
(2) 利用具名方法(Named Methods)初始化delegate物件
1: delegate void Printer(string s);
2: static void DoWork(string k)
3: { 4: System.Console.WriteLine(k); 5: }6: private void button5_Click(object sender, EventArgs e)
7: {8: Printer p = delegate(string str) // (1) 利用匿名方法初始化delegate
9: { 10: System.Console.WriteLine(str); 11: };12: // Results from the anonymous delegate call.
13: p("(1)匿名方法(Anonymous Method)傳給delegate");
14: //------------------------------------------------------------------
15: p = new Printer(DoWork); // (2)利用命名方法初始化delegate
16: // Results from the old style delegate call.
17: p("(2)命名方法(Named Method)傳給delegate");
18: 19: }
附註:
在 C# 2.0 以前的版本中,宣告委派 (Delegate) 的唯一方式是使用具名方法(Named Methods)。
C# 2.0 引進了匿名方法 (Anonymous Method)
C# 3.0 (含) 以後版本,則以 Lambda 運算式取代匿名方法來做為撰寫內嵌 (Inline) 程式碼的慣用方式。





留言列表
