加入 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) 程式碼的慣用方式。
留言列表