c# 委託和 lambda
阿新 • • 發佈:2022-04-01
一、委託
委託定義指定特定方法簽名的型別。 可將滿足此簽名的方法(靜態或例項)分配給該型別的變數,然後(使用適當引數)直接呼叫該方法,或將其作為引數本身傳遞給另一方法再進行呼叫。 以下示例演示了委託的用法。
using System; using System.Linq; public class Program { public delegate string Reverse(string s); static string ReverseString(string s) { return new string(s.Reverse().ToArray()); }static void Main(string[] args) { Reverse rev = ReverseString; Console.WriteLine(rev("a string")); } }
-
-
public delegate string Reverse(string s);
行建立特定簽名的委託型別,在本例中即接受字串引數並返回字串引數的方法。 -
static string ReverseString(string s)
方法與定義的委託型別具有完全相同的簽名,用於實現委託。 -
Reverse rev = ReverseString;
-
Console.WriteLine(rev("a string"));
行演示如何使用委託型別的變數來呼叫委託
-
-
為簡化開發過程,.NET 包含一組委託型別,程式設計師可重用這些型別而無需建立新型別。 這些型別是
Func<>
、Action<>
和Predicate<>
,可以使用它們而無需定義新的委託型別。 這三種類型之間有一些區別,與它們的預期使用方式有關:-
Action<>
用於需要使用委託引數執行操作的情況。 它所封裝的方法不返回值。 -
Func<>
通常用於現有轉換的情況,也就是說需要將委託引數轉換為其他結果時。 投影是一個很好的示例。 它所封裝的方法返回指定值。 -
Predicate<>
用於需要確定引數是否滿足委託條件的情況。 它也可以編寫為Func<T, bool>
,這意味著方法返回布林值。
-
using System; using System.Linq; public class Program { static string ReverseString(string s) { return new string(s.Reverse().ToArray()); } static void Main(string[] args) { Func<string, string> rev = ReverseString; Console.WriteLine(rev("a string")); } }
匿名委託
對於此簡單示例而言,在 Main
方法之外定義方法似乎有些多餘。 .NET Framework 2.0 引入了匿名委託的概念,使你可以建立“內聯”委託,而無需指定任何其他型別或方法。
在下面的示例中,匿名委託將列表篩選為只包含偶數,然後將它們列印到控制檯。
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll( delegate (int no) { return (no % 2 == 0); } ); foreach (var item in result) { Console.WriteLine(item); } } }
三、lambda 表示式
但是,即使使用此方法,仍有許多可以丟棄的程式碼。 此時就需要使用 lambda 表示式。 lambda 表示式(或簡稱“lambda”)在 C# 3.0 中作為語言整合查詢 (LINQ) 的核心構建基塊被引入。 這種表示式只是使用委託的更方便的語法。 它們將宣告簽名和方法正文,但在分配到委託之前沒有自己的正式標識。 與委託不同,可將其作為事件註冊的右側內容或在各種 LINQ 子句和方法中直接分配。
由於 lambda 表示式只是指定委託的另一種方式,因此應可重新編寫上述示例,令其使用 lambda 表示式而不是匿名委託。
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll(i => i % 2 == 0); foreach (var item in result) { Console.WriteLine(item); } } }
再次強調,lambda 只是委託,這意味著可將其順利用作事件處理程式,如以下程式碼片段所示。
public MainWindow() { InitializeComponent(); Loaded += (o, e) => { this.Title = "Loaded"; }; }
此上下文中的 +=
運算子用於訂閱事件。 有關詳細資訊,請參閱如何訂閱和取消訂閱事件。