C#lambda表示式

【君莫笑】發表於2024-04-12
一、介紹
無引數 ()
=>{return "1";}; 等同於 string getnum(){ return "1"; } 有兩個引數 (p1, p2) =>{ return p1*p2;}; 等同於 int mul(p1, p2) { return p1*p2;};

lambda表示式可以捕獲外部變數,並在其主體中使用它們。這些變數被稱為捕獲變數,它們會在lambda表示式建立時被複制,並在lambda表示式執行時被更新。例如:

  int factor = 2;
  Func<int, int> multiplier = n => n * factor;
  Console.WriteLine(multiplier(3)); //輸出6
  factor = 3;
  Console.WriteLine(multiplier(3)); //輸出9

二、lambda演進過程
//宣告委託型別
public delegate void SayHandler(string name, int age);
//原始形態
SayHandler handler1=new SayHandler(  
    delegate(string name, int age){ Console.WriteLine("你好"); }
);
//進化1  直接去掉:new SayHandler( )
SayHandler handler2=delegate(string name, int age)
{ 
  Console.WriteLine("你好"); 
}
//進化2 delegate去掉後,換上了一個符號“=>”,讀作:goes to
SayHandler handler3=(string name, int age)=>{ Console.WriteLine("你好"); }
//進化3 因為與委託型別是一一對應關係,所以直接去掉引數型別名稱
SayHandler handler4=(name, age)=>{ Console.WriteLine("你好"); }
//進化4 匿名方法只有一行程式碼,則花括號{} 可省略
//注:若引數列表中只有一個引數,則圓括號() 也可省略
SayHandler handler5=(name, age)=> Console.WriteLine("你好"); 


三、lambda表示式的5中高頻使用方法

第一種 使用lambda表示式作為委託或事件處理程式

1.1 委託是一種引用型別,它可以封裝一個具有特定引數和返回值型別的方法。委託可以用來實現回撥函式、事件處理程式、匿名方法等功能。lambda表示式可以直接表示為委託的程式碼,而不需要單獨定義一個方法或一個委託型別。這樣可以簡化委託的建立和使用,提高程式碼的可讀性和靈活性。

//定義一個委託型別
delegate int CalculateHandler(int x, int y);
//建立一個lambda表示式,並賦值給一個委託變數 CalculateHandler sumHandler = (x, y) => x + y; //呼叫委託變數,執行lambda表示式的主體 Console.WriteLine(sumHandler(1, 2)); //輸出3//使用系統預定義的泛型委託型別 Func<int, int, int> multiplyHandler = (x, y) => x * y; //呼叫委託變數,執行lambda表示式的主體 Console.WriteLine(multiplyHandler(2, 3)); //輸出6//直接將lambda表示式作為引數傳遞給其他方法 List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 }; numbers.ForEach(n => Console.WriteLine(n * n)); //輸出1 4 9 16 25

1.2 事件是一種特殊的委託,它可以在某個物件發生特定行為時通知其他物件。事件處理程式是一種特殊的方法,它可以在事件被觸發時執行一些操作。lambda表示式可以直接表示為事件處理程式的程式碼,而不需要單獨定義一個方法。這樣可以簡化事件處理程式的建立和使用,提高程式碼的可讀性和靈活性。

//定義一個按鈕類
class Button
{ //定義一個點選事件
public event EventHandler Click;
//定義一個觸發點選事件的方法
public void OnClick()
{ //如果有訂閱了該事件的處理程式,則呼叫它們 Click?.Invoke(this, EventArgs.Empty); } } //建立一個按鈕物件 Button button = new Button(); //建立一個lambda表示式,並新增到點選事件的訂閱列表中 button.Click += (sender, e) => { Console.WriteLine("Button clicked"); }; //觸發點選事件,執行lambda表示式的主體 button.OnClick(); //輸出Button clicked

第二種:使用lambda表示式作為LINQ查詢的謂詞或選擇器

LINQ是一種語言整合查詢,它可以用來對各種資料來源進行查詢、篩選、排序、分組等操作。LINQ查詢可以使用查詢表示式或方法語法來編寫,其中方法語法可以使用lambda表示式來指定查詢的條件或投影。lambda表示式可以直接表示為謂詞或選擇器的程式碼,而不需要單獨定義一個方法。這樣可以簡化LINQ查詢的建立和使用,提高程式碼的可讀性和靈活性。

//定義一個資料來源
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
 
//建立一個lambda表示式,並作為引數傳遞給Where方法,篩選出偶數
var evenNumbers = numbers.Where(n => n % 2 == 0);
//遍歷LINQ查詢結果,執行lambda表示式的主體
foreach (var n in evenNumbers)
{ Console.WriteLine(n); //輸出2 4 } //建立一個lambda表示式,並作為引數傳遞給Select方法,將每個數乘以10
var multipliedNumbers = numbers.Select(n => n * 10);
//遍歷LINQ查詢結果,執行lambda表示式的主體
foreach (var n in multipliedNumbers)
{ Console.WriteLine(n); //輸出10 20 30 40 50 } //建立一個lambda表示式,並作為引數傳遞給OrderBy方法,按照數值大小排序
var sortedNumbers = numbers.OrderBy(n => n);
//遍歷LINQ查詢結果,執行lambda表示式的主體foreach (var n in sortedNumbers) { Console.WriteLine(n); //輸出1 2 3 4 5 }

第三種:使用lambda表示式作為Task.Run或Task.Factory.StartNew的引數

Task是一種表示非同步操作的物件,它可以用來實現並行程式設計、非同步程式設計、多執行緒程式設計等功能。Task可以使用Task.Run或Task.Factory.StartNew方法來建立和啟動,這些方法可以接受一個委託作為引數,表示要在任務中執行的程式碼。lambda表示式可以直接表示為委託的程式碼,而不需要單獨定義一個方法。這樣可以簡化Task的建立和使用,提高程式碼的可讀性和靈活性。

//建立一個lambda表示式,並作為引數傳遞給Task.Run方法,建立並啟動一個任務
var task = Task.Run(() =>
{ //在任務中執行一些耗時的操作 Thread.Sleep(1000); //返回一個結果 return 42; }); //等待任務完成,獲取任務的結果 int result = task.Result; Console.WriteLine(result); //輸出42 //建立一個lambda表示式,並作為引數傳遞給Task.Factory.StartNew方法,建立並啟動一個任務 var task2 = Task.Factory.StartNew(() => { //在任務中執行一些耗時的操作 Thread.Sleep(1000); //丟擲一個異常 throw new Exception("Something went wrong"); }); //等待任務完成,獲取任務的異常 try { task2.Wait(); } catch (AggregateException ae) { foreach (var e in ae.InnerExceptions) { Console.WriteLine(e.Message); //輸出Something went wrong } }

第四種 使用lambda表示式作為表示式樹

表示式樹是一種表示程式碼結構的資料結構,它可以用來實現動態編譯、超程式設計、LINQ提供程式等功能。表示式樹可以使用Expression<TDelegate>型別來建立和表示,這是一種特殊的委託型別,它可以接受一個lambda表示式作為引數,表示要在表示式樹中表示的程式碼。lambda表示式可以直接表示為表示式樹的程式碼,而不需要單獨定義一個方法。這樣可以簡化表示式樹的建立和使用,提高程式碼的可讀性和靈活性。

//建立一個lambda表示式,並作為引數傳遞給Expression<Func<int, int, int>>型別的建構函式,建立一個表示式樹物件
Expression<Func<int, int, int>> expression = (x, y) => x + y;
 
//遍歷表示式樹物件,獲取表示式樹的結構
Console.WriteLine(expression); //輸出(x, y) => (x + y)
Console.WriteLine(expression.Body); //輸出(x + y)
Console.WriteLine(expression.Parameters[0]); //輸出x
Console.WriteLine(expression.Parameters[1]); //輸出y//轉換表示式樹物件,編譯為委託
Func<int, int, int> func = expression.Compile();
 
//呼叫委託,執行lambda表示式的主體
Console.WriteLine(func(1, 2)); //輸出3

第五種 使用lambda表示式作為非同步方法

非同步方法是一種使用async和await關鍵字來實現非同步程式設計的方法,它可以用來實現非阻塞的UI、併發的網路請求、非同步的IO操作等功能。非同步方法可以使用Task或Task<T>型別來表示非同步操作的結果,它們可以接受一個lambda表示式作為引數,表示要在非同步方法中執行的程式碼。lambda表示式可以直接表示為非同步方法的程式碼,而不需要單獨定義一個方法。這樣可以簡化非同步方法的建立和使用,提高程式碼的可讀性和靈活性。

關鍵字來標記非同步處理的程式碼,並使用await關鍵字來等待非同步操作的完成。
- 將lambda表示式作為引數傳遞給Task或Task<T>型別的方法,如Task.Run或Task.FromResult,建立並啟動一個非同步方法。
- 等待非同步方法完成,獲取非同步方法的結果或異常。
 
例如,下面的程式碼演示瞭如何使用lambda表示式作為非同步方法:
 
//建立一個lambda表示式,並作為引數傳遞給Task.Run方法,建立並啟動一個非同步方法
var task = Task.Run(async () =>
{ //在lambda表示式中使用async和await關鍵字來標記非同步處理的程式碼await Task.Delay(1000); //等待1秒return42; //返回一個結果 }); //等待非同步方法完成,獲取非同步方法的結果
int result = await task;
Console.WriteLine(result); //輸出42//建立一個lambda表示式,並作為引數傳遞給Task.FromResult方法,建立並啟動一個非同步方法
var task2 = Task.FromResult(async () =>
{ //在lambda表示式中使用async和await關鍵字來標記非同步處理的程式碼await Task.Delay(1000); //等待1秒thrownew Exception("Something went wrong"); //丟擲一個異常 }); //等待非同步方法完成,獲取非同步方法的異常try { await task2; } catch (Exception e) { Console.WriteLine(e.Message); //輸出Something went wrong }
  

來源:https://blog.csdn.net/polsnet/article/details/129711365

相關文章