1. Lambda表達(dá)式
“Lambda” 表達(dá)式”是一個(gè)匿名函數(shù),,用于創(chuàng)建委托或表達(dá)式樹(shù)類(lèi)型。
“=>”為L(zhǎng)ambda 運(yùn)算符,,讀為“goes to”,。Lambda 運(yùn)算符左邊是“輸入?yún)?shù)”,右邊是“表達(dá)式或語(yǔ)句塊”,,如下所示:
1 2 3 4 5 6 | delegate int del( int i);
static void Main( string [] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
|
使用“Lambda 表達(dá)式”請(qǐng)注意一下幾點(diǎn):
1)=> 運(yùn)算符具有與賦值運(yùn)算符 (=) 相同的優(yōu)先級(jí),,并且是右結(jié)合運(yùn)算符。
2)在 is 或 as 運(yùn)算符的左側(cè)不允許使用 Lambda,。
3)適用于匿名方法的所有限制也適用于 Lambda 表達(dá)式,,如:Lambda 語(yǔ)句無(wú)法用于創(chuàng)建表達(dá)式樹(shù),。
4)只有在 Lambda 有一個(gè)輸入?yún)?shù)時(shí),括號(hào)才是可選的,,否則括號(hào)是必需的,,兩個(gè)或更多輸入?yún)?shù)由括在括號(hào)中的逗號(hào)分隔。
5)有時(shí),,編譯器難于或無(wú)法推斷輸入類(lèi)型,,如果出現(xiàn)這種情況,顯式指定類(lèi)型:
1 | ( int x, string s) => s.Length > x
|
6)使用空括號(hào)指定零個(gè)輸入?yún)?shù):
7)Lambda 語(yǔ)句的主體可以包含任意數(shù)量的語(yǔ)句,,但在實(shí)際運(yùn)用中,,不會(huì)多于兩個(gè)或三個(gè)語(yǔ)句。
1 2 3 4 | delegate void TestDelegate( string s);
…
TestDelegate myDel = n => { string s = n + " " + "World" ; Console.WriteLine(s); };
myDel( "Hello" );
|
8)在編寫(xiě) Lambda 時(shí),,通常不必為輸入?yún)?shù)指定類(lèi)型,,因?yàn)榫幾g器可以根據(jù) Lambda 主體、基礎(chǔ)委托類(lèi)型以及 C# 語(yǔ)言規(guī)范中描述的其他因素推斷類(lèi)型,。Lambda 表達(dá)式本身沒(méi)有類(lèi)型,,但是,有時(shí)會(huì)不正式地論及 Lambda 表達(dá)式的“類(lèi)型”,,在這些情況下,類(lèi)型是指委托類(lèi)型或 Lambda 表達(dá)式所轉(zhuǎn)換為的 Expression 類(lèi)型,。Lambda 的一般規(guī)則如下:
- Lambda 包含的參數(shù)數(shù)量必須與委托類(lèi)型包含的參數(shù)數(shù)量相同,。
- Lambda 中的每個(gè)輸入?yún)?shù)必須都能夠隱式轉(zhuǎn)換為其對(duì)應(yīng)的委托參數(shù)。
- Lambda 的返回值(如果有)必須能夠隱式轉(zhuǎn)換為委托的返回類(lèi)型,。
9)Lambda 可以引用“外部變量”,,這些變量位于在其中定義 Lambda 的封閉方法或類(lèi)型的范圍內(nèi)。 將會(huì)存儲(chǔ)通過(guò)這種方法捕獲的變量以供在 Lambda 表達(dá)式中使用,,即使變量將以其他方式超出范圍或被作為垃圾回收,。 必須明確地分配外部變量,然后才能在 Lambda 表達(dá)式中使用該變量,。如下例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | using System;
delegate bool D();
delegate bool D2( int i);
class Test
{
D del;
D2 del2;
public void TestMethod( int input)
{
int j = 0;
// del在方法體內(nèi)被調(diào)用
del = () => { j = 10; return j > input; };
// del2在外部調(diào)用
del2 = (x) => { return x == j; };
// 輸出: j = 0
Console.WriteLine( "j = {0}" , j);
// 調(diào)用委托
bool boolResult = del();
// 輸出: j = 10 b = True
Console.WriteLine( "j = {0}.b = {1}" , j, boolResult);
}
static void Main()
{
Test test = new Test();
test.TestMethod(5);
// del2 仍然保存TestMethod方法的局部變量j
bool result = test.del2(10);
// 輸出: True
Console.WriteLine(result);
Console.ReadKey();
}
}
|
10)下列規(guī)則適用于 Lambda 表達(dá)式中的變量范圍:
- 捕獲的變量將不會(huì)被作為垃圾回收,,直至引用變量的委托超出范圍為止。
- 在外部方法中看不到 Lambda 表達(dá)式內(nèi)引入的變量,。
- Lambda 表達(dá)式無(wú)法從封閉方法中直接捕獲 ref 或 out 參數(shù),。
- Lambda 表達(dá)式中的返回語(yǔ)句不會(huì)導(dǎo)致封閉方法返回。
- Lambda 表達(dá)式不能包含其目標(biāo)位于所包含匿名函數(shù)主體外部或內(nèi)部的 goto 語(yǔ)句,、break 語(yǔ)句或 continue 語(yǔ)句,。
2. Predicate 泛型委托
“Predicate 泛型委托”表示定義一組條件并確定指定對(duì)象是否符合這些條件的方法,其本質(zhì)為一委托,,在該委托中定義一組條件,,用以判斷傳入對(duì)象是否符合這些條件,,如果符合,返回True,,如果不符合,,返回false。
語(yǔ)法:
1 2 3 | public delegate bool Predicate<T> (
T obj
)
|
類(lèi)型參數(shù)說(shuō)明:
- T:要比較的對(duì)象的類(lèi)型,。
- obj:要按照由此委托表示的方法中定義的條件進(jìn)行比較的對(duì)象,。
- 返回值:如果 obj 符合由此委托表示的方法中定義的條件,則為 true,;否則為 false,。
此委托由 Array 和 List 類(lèi)的幾種方法使用,用于在集合中搜索元素:
Array : public T[] FindAll<T>(T[] array, Predicate<T> match),;
List:public List<T> FindAll(Predicate<T> match),;
下面給出兩個(gè)例子,第一個(gè)例子演示“Predicate 泛型委托”在Array,、List集合中的應(yīng)用,,第二個(gè)例子演示“Predicate 泛型委托”的拓展應(yīng)用。
例子一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public class GenericDelegateDemo
{
List<String> listString = new List<String>()
{
"One" , "Two" , "Three" , "Four" , "Fice" , "Six" , "Seven" , "Eight" , "Nine" , "Ten"
};
String[] arrayString = new String[]
{
"One" , "Two" , "Three" , "Four" , "Fice" , "Six" , "Seven" , "Eight" , "Nine" , "Ten"
};
public String[] GetFirstStringFromArray()
{
return Array.FindAll(arrayString, (c) => { return c.Length <= 3; });
}
public List<String> GetFirstStringFromList()
{
return listString.FindAll((c) => { return c.Length <= 3; });
}
public String[] GetFirstStringFromArray_1()
{
return Array.FindAll(arrayString, GetString);
}
public List<String> GetFirstStringFromList_1()
{
return listString.FindAll(GetString);
}
private bool GetString(String str)
{
if (str.Length <= 3)
return true ;
else
return false ;
}
}
|
例子二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class GenericDelegateDemo
{
List<String> listString = new List<String>() { "One" , "Two" , "Three" , "Four" , "Fice" , "Six" , "Seven" , "Eight" , "Nine" , "Ten" };
public String GetStringList(Predicate<String> p)
{
foreach ( string item in listString)
{
if (p(item))
return item;
}
return null ;
}
public bool ExistString()
{
string str = GetStringList(a => { return a.Length <= 3 && a.Contains( 'S' ); });
if (str == null )
return false ;
else
return true ;
}
}
|
|