close

image

「Lambda 運算式」(Lambda Expression) 是一種匿名函式

它可以包含運算式和陳述式 (Statement),而且可以用來建立委派 (Delegate)

 

  1. 所有的 Lambda 運算式都會使用 Lambda 運算子 =>,意思為「移至」。
  2. Lambda 運算子的左邊會指定輸入參數 (如果存在),右邊則包含運算式或陳述式區塊。
  3. Lambda 運算式 x => x * x 的意思是「x 移至 x 乘以 x」。
  4. 這個運算式可以指派給委派型別 (Delegate Type),如下

image

   1: delegate int power2(int x);
   2: delegate int power3(int x);
   3: delegate int power5(int x);
   4: private void button1_Click(object sender, EventArgs e)
   5: {
   6:     power2 p2 = x => x * x;                // x to the power of 2
   7:     power3 p3 = x => p2(x) * x;            // x to the power of 3
   8:     power5 p5 = x => p2(x) * p3(x);        // x to the power of 5 
   9:     MessageBox.Show("2的2次方 =" + p2(2).ToString());
  10:     MessageBox.Show("2的3次方 =" + p3(2).ToString());
  11:     MessageBox.Show("2的5次方 =" + p5(2).ToString());
  12: }

image

   1: private void button2_Click(object sender, EventArgs e)
   2:        {
   3:            // (2) Anonymous Methods匿名方法
   4:            power2 p2 = delegate(int x) { return x * x; };
   5:            power3 p3 = delegate(int x) { return p2(x) * x; };
   6:            power5 p5 = delegate(int x) { return p2(x) * p3(x); };
   7:            MessageBox.Show("2的2次方 =" + p2(2).ToString());
   8:            MessageBox.Show("2的3次方 =" + p3(2).ToString());
   9:            MessageBox.Show("2的5次方 =" + p5(2).ToString());
  10:        }

image

   1: static int powerOf2(int x) { return x * x; }
   2: static int powerOf3(int x) { return powerOf2(x) * x; }
   3: static int powerOf5(int x) { return powerOf2(x) * powerOf3(x); }
   4:  
   5: private void button3_Click(object sender, EventArgs e)
   6: {
   7:     power2 p2 = new power2(powerOf2);
   8:     power3 p3 = new power3(powerOf3);
   9:     power5 p5 = new power5(powerOf5);
  10:     MessageBox.Show("2的2次方 =" + p2(2).ToString());
  11:     MessageBox.Show("2的3次方 =" + p3(2).ToString());
  12:     MessageBox.Show("2的5次方 =" + p5(2).ToString());
  13: }

Lambda 兩個輸入引數

   1: // Lambda 兩個輸入引數
   2: delegate int maxAbs(int x, int y);
   3: private void button4_Click(object sender, EventArgs e)
   4: {
   5:     maxAbs ma = (x, y) => Math.Abs(x) > Math.Abs(y) ? Math.Abs(x) : Math.Abs(y);
   6:     int X  = -3;
   7:     int Y = -2;
   8:     MessageBox.Show( String.Format("X = {0}, Y= {1}, maxAbs(X,Y) = {2}",X, Y, ma(X, Y)) );
   9: }

image

--------------------------------------------------------------------------------------------------------------------------------------------------

有時候編譯器會很難或是無法推斷輸入型別。 當這種情形發生時,您就可以明確指定型別

   1: delegate bool CheckStrLen(string str, int len);
   2:  
   3:  private void button5_Click(object sender, EventArgs e)
   4:  {
   5:      CheckStrLen chkStr = (string str, int x) => str.Length > x;
   6:      string s = "Hello World";
   7:      int len = 5;
   8:      MessageBox.Show( string.Format("{0}長度大於{1}: {2}",s, len, chkStr(s, len)) );
   9:  }

image

--------------------------------------------------------------------------------------------------------------------------------------------------

Lambda 零個輸入引數

   1: Thread th;
   2:        bool _shouldStop = false;
   3:        private void button6_Click(object sender, EventArgs e)
   4:        {
   5:            th = new Thread(
   6:                () =>
   7:                {
   8:                    while (!_shouldStop)
   9:                    {
  10:                        Invoke(
  11:                              (MethodInvoker) 
  12:                              (() =>
  13:                              {
  14:                                  label1.Text = DateTime.Now.ToString("F");
  15:                              })
  16:                              
  17:                        );
  18:                        Thread.Sleep(1000);
  19:                    }
  20:                }
  21:             );
  22:            th.IsBackground = true;
  23:            th.Start();
  24:        }
  1. Invoke: 在目前執行緒中執行特定匿名方法輸入個數為零的Lambda Expression, 但該delegate方法包含視窗上的控制元件, 不屬於目前的執行緒
  2. 必須將 Lambda 運算式所包含的code block() 轉型為  (MethodInvoker), 其中MethodInvoker 表示可以宣告為 void,而且不接受參數的 managed 程式碼中執行的任何方法的委派

image

加入Form_Closing

   1: private void Form1_FormClosing(object sender, FormClosingEventArgs e)
   2: {
   3:     _shouldStop = true;
   4:     if (th != null && th.IsAlive)
   5:         th.Abort();
   6: }

image

--------------------------------------------------------------------------------------------------------------------------------------------------

Invoke(…)嘗試另一種寫法: 上面的範例是呼叫Lambda Expression, 下面這個範例是呼叫匿名方法

   1: delegate void showTime();          // 委派 showTime 輸出個數=0
   2:     private void button7_Click(object sender, EventArgs e)
   3:     {
   4:         // 初始化匿名方法
   5:         showTime s = delegate() { label1.Text = DateTime.Now.ToString("F"); };
   6:         th = new Thread(
   7:             () =>
   8:             {
   9:                 MethodInvoker method = new MethodInvoker(s);
  10:                 while (!_shouldStop)
  11:                 {
  12:                     Invoke( method );   // 執行匿名方法
  13:                     Thread.Sleep(1000);
  14:                 }
  15:             }
  16:             );
  17:         th.Start();
  18:     }

image

 

 

附註:

在 C# 2.0 以前的版本中,宣告委派 (Delegate) 的唯一方式是使用具名方法(Named Methods)。

C# 2.0 引進了匿名方法 (Anonymous Method)

C# 3.0 (含) 以後版本,則以 Lambda 運算式取代匿名方法來做為撰寫內嵌 (Inline) 程式碼的慣用方式。

 

相關資料:

  1. Lambda 運算式 (C# 程式設計手冊)

  2. C# Delegates with Anonymous Methods(匿名方法)and Named Methods(具名方法)

  3. Control.Invoke 方法 (Delegate)

  4. MethodInvoker 委派

arrow
arrow
    全站熱搜

    me1237guy 發表在 痞客邦 留言(0) 人氣()