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