YehYeh 記事本2.0

Version 0.8.3

竹科碼農的記事本

Lambda 運算式

委派

  • 變數的型別不能是函式,只能是類別、int、String、…

    • 在C++中,函式指標(Function Pointer)可以讓變數指向函式
    • 在JavaScript中,變數可以是函式
      • var func = function sum(a, b){ return a+ b}
  • 在C#中,要把函式當作變數來使用,就要用委派

  • 委派可以作為函式的參數 ⇒ 可以用來回呼(Call back)

  • 委派鏈 ⇒ 委派可以連結在一起 ⇒ 一個事件可以呼叫多個方法

  • Delegate可以有0~32個參數

委派的類型

委派 說明
Delegate 需宣告自訂委派
Action 不需宣告自訂委派, 無回傳值委派
Func 不需宣告自訂委派,有回傳值委派
predicate 不需宣告自訂委派,回傳值為bool型別委派

實作一個委派

  1. 宣告自訂委派 : 由於函式有回傳型別,輸入參數,所以使用委派要先定義 ⇒ 定義一個委派類別
  • public delegate 回傳型別 MyDel(輸入參數)
  1. 要實作函式的本體 ⇒ 回傳型別與輸入參數需要與委派一樣
  • public static void DelegateMethod1(string msg) { Console.WriteLine(msg); }
  1. 將委派類別實體化
  • MyDel handler = DelegateMethod1;
  1. 呼叫函式
  • handler();

例1-1 定義委派及函式

// 定義一個委派(回傳值, 名字, 參數) => 可以想像宣告一個指標
public delegate void MyDel(string msg); 

// 實作委派的方法 => 實作一個函式
public static void DelegateMethod1(string msg)
{
    Console.WriteLine(msg);
}

public static void DelegateMethod2(string msg)
{
    Console.WriteLine("Hello: " + msg);
}

例1-2 執行

MyDel handler = DelegateMethod1;     // handler為MyDel型別,指向DelegateMethod
handler("World");             // 執行委派

handler = DelegateMethod2;
handler("World");

例1-3 回呼

public static void MyDelCallback( string name, MyDel callback)
{
    callback( name );
}

例1-4 委派鏈

MyDel handler = null;
handler += DelegateMethod1;   // 鏈結委派
handler += DelegateMethod2;   // 鏈結委派

handler();    // 執行 DelegateMethod1 和 DelegateMethod2

handler -= DelegateMethod1;   // 將委派由委派鏈中移除

Action

public class Name
{
    public void DisplayToWindow()
    {
      MessageBox.Show("My name is yehyeh");
    }
}

Name myName = new Name();

Action showMethod = testName.DisplayToWindow;
Action showMethod = () => testName.DisplayToWindow();
Action showMethod = delegate() { testName.DisplayToWindow();} ;

Lambda 運算式

  • Lambda是一種匿名函式
  • Lambda可以分成2種
    • 以運算式為主體 (輸入參數) => expression
    • 以陳述式區塊為主體 (輸入參數) => {敘述}
  • => 用來將lambda左側的輸入和右側的主體分開
    • 念作 goes to
  • Lambda 一定可轉成委派型別
    • Lambda無回傳值 → 可轉換成Action委派型別
    • Lambda有回傳值 → 可轉換成Func委派型別

以運算式為主體 Lambda

// Lambda無輸入參數
Action line = () => Console.WriteLine();

// Lambda輸入參數無指定型別
Func<int, int, bool> testForEquality = (x, y) => x == y;

// 編譯器無法判斷型別時,需自行定義型別
Func<int, string, bool> isTooLong = (int x, string s) => s.Length > x;

以陳述式區塊為主體 Lambda

Action<string> greet = name => 
{ 
    string greeting = $"Hello {name}!";
    Console.WriteLine(greeting);            // Hello World;
};
greet("World");     

Lambda 運算式和元組

  • C# 7.0 開始,支援元組(tuples)
    • 可以將元組當做引數提供給 Lambda 運算式
    • Lambda 運算式可以傳回元組。
// 將元組當做引數
Func<(int, int, int), (int, int, int)> doubleThem = ns => (2 * ns.Item1, 2 * ns.Item2, 2 * ns.Item3);

var numbers = (2, 3, 4);
var doubledNumbers = doubleThem(numbers);

Console.WriteLine($"The set {numbers} doubled: {doubledNumbers}");
// Output:
// The set (2, 3, 4) doubled: (4, 6, 8)

參考

Last updated on 2020-04-08
Published on 2020-04-08
Edit on GitHub