匿名方法和Lambda表示式
阿新 • • 發佈:2022-04-09
匿名方法和Lambda表示式
1、匿名方法
在C#2.0版本中引入了匿名方法,匿名方法與具名方法(即普通的方法)相對
簡單示例:
delegate void MyDelegate(int x); //宣告一個委託型別
void Main()
{
MyDelegate del = delegate(int x)
{
Console.WriteLine($"匿名方法輸出值:{x}");
};
del(20);
}
使用場景
- 給初始化委託變數
- 給組合委託賦值
- 給委託增加方法
語法
匿名方法必須與關聯的委託保持格式一致,也就是返回值和引數需要相同,注意語句塊後面是有分號的,不要漏掉
delegate(引數列表) {語句塊};
返回值
匿名方法不會顯示地宣告返回值,但是返回值要和對應的委託保持一致。如果委託沒有返回值,即為void時,匿名方法則不能有返回值;如果委託有返回值,則匿名函式需要在語句塊中返回對應型別的值。
delegate int MyDelegate(int x); //宣告一個委託型別
void Main()
{
MyDelegate del = delegate(int x)
{
Console.WriteLine($"匿名方法輸出值:{x}");
return (x + 10);
};
}
引數列表
引數列表要和宣告的委託保持一致,也就是引數的個數、型別及位置。
當委託沒有out引數或匿名方法沒有輸入引數時,則可以省略匿名方法的引數列表。當匿名方法不需要輸入引數時,這種情況下引數列表可以和委託不一致了,但同時在呼叫委託時,傳入的引數也不會起到作用。
delegate int MyDelegate(int x); //宣告一個委託型別
void Main()
{
MyDelegate del = delegate
{
Console.WriteLine($"匿名方法不需要使用輸入引數");
return 10;
};
del(20);
}
如果在委託型別的宣告中,引數列表使用了params引數,則匿名方法的引數列表會忽略params關鍵字的作用。
外部變數的捕獲
在匿名方法中使用方法塊外部的變數很簡單,可以直接使用
delegate int MyDelegate(int x); //宣告一個委託型別 void Main() { int val = 20; MyDelegate del = delegate { //捕獲匿名方法外部的val變數 Console.WriteLine($"匿名方法輸出:{val+10}"); return 10; }; del(20); }
輸出:
匿名方法輸出:30
捕獲變數的生命週期會在委託被呼叫時得到擴充套件
MyDelegate del;
{
int val = 20; //val變數的作用域和生命週期在此程式碼塊中
del = delegate
{
Console.WriteLine($"匿名方法輸出:{val + 10}");
return 10;
};
}
del(20); //委託呼叫時,由於匿名方法捕獲了val變數,val變數的生命週期在此得到延續
2、Lambda表示式
在C#3.0中引入Lambda,簡化了匿名方法,用來替代匿名方法。lambda表示式相比匿名方法,不需要使用delegate關鍵字,並且有更精簡的寫法,易於理解也提高了效率。
使用場景
和匿名方法一樣,作為委託delegate的初始化方法或給委託增加方法
還可以用在屬性的get、set中
語法格式
Lambda運算子=>,讀作 goes to
引數列表 => 方法塊
示例:
delegate void MyDelegate(int x); //宣告一個委託型別
void Main()
{
MyDelegate del;
del = delegate (int x) { Console.WriteLine($"匿名方法輸出:{x}"); }; //匿名方法
del = (int x) => { Console.WriteLine($"Lambda表示式輸出:{x}"); }; //lambda表示式
del(20);
}
帶返回值
delegate int MyDelegate1(int x); //宣告一個委託型別
void Main()
{
MyDelegate1 del1;
del1 = x =>
{
Console.WriteLine($"Lambda表示式輸出:{x}");
return 10;
};
del1(100);
}
引數列表
- 引數列表一般來說格式要和委託型別保持一致
- 沒有引數時,必須要用空的()來表示
- 只有一個引數時,可以省略()
- Lambda表示式中引數型別可以省略,除非委託引數中有ref和out修飾的引數,則不可省略
引數列表帶有型別稱為顯示型別,沒有型別稱為隱式型別
delegate void MyDelegate(int x); //宣告一個委託型別
void Main()
{
MyDelegate del;
del = (int x) => { Console.WriteLine($"Lambda表示式輸出:{x}"); };
del = (x) => { Console.WriteLine($"Lambda表示式輸出:{x}"); }; //省略型別
del = x => { Console.WriteLine($"Lambda表示式輸出:{x}"); }; //省略()
del = x => Console.WriteLine($"Lambda表示式輸出:{x}"); //只有一條語句,也可以放return的表示式
del(20);
}
多個引數
delegate int MyDelegate2(int x, int y, int z); //宣告一個委託型別
void Main()
{
MyDelegate2 del2, del3, del4;
del2 = (int x, int y, int z) =>
{
Console.WriteLine($"x = {x}, y = {y}, z = {z}");
return 20;
};
del3 = (x, y, z) => x + y + z; //省略引數型別,一個語句作為return表示式
//del4 = x, y, z => x + y + z; //多個引數時無法省略()
del2(3, 5, 7);
Console.WriteLine(del3(3, 5, 7));
}
輸出
x = 3, y = 5, z = 7
15