其他答案錯過了lambda表達式不一定代表方法的事實。有時候,他們代表表達式樹。
根據上下文,編譯器將lambda表達式隱式轉換爲一種類型的對象或另一種類型的對象。
要指定方法,您需要指定參數和主體。在lambda表達式中,這些用=>
分開。實例:
() => 4; //empty parameter list
x => x.ToString(); //one parameter
(a, b) => a.Equals(b); //two parameters
// ^^^^^^ ^^^^^^^^^^^^
// | |
// parameter list body
這些lambda表達式可以分別轉化爲Func<int>
,Func<object, string>
,和Func<object, object, bool>
。也可以分別轉換爲Expression<Func<int>>
,Expression<Func<object, string>>
和Expression<Func<object, object, bool>>
。
匿名方法:
delegate (object p, object q) { return string.Concat(p, q); }
// ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// parameter list body
下面是拉姆達轉換的兩個例子:
Func<object, object, bool> aDelegate = (o1, o2) => object.Equals(o1, o2);
Expression<Func<object, object, bool>> anExpressionTree = (o1, o2) => object.Equals(o1, o2);
在方法組轉換,參數和方法主體被重載解析指定。爲了簡化一下,編譯器查看具有指定名稱的方法,並根據上下文選擇正確的過載。例如,考慮SquareMethod的這些重載:
int SquareMethod(int a) { return a * a; }
double SquareMethod(double a) { return a * a; }
這些陳述涉及方法組轉換和重載決議:
Func<int, int> squareAnInt = SquareMethod;
Func<double, double> squareADouble = SquareMethod;
最後,lambda表達式不能轉換爲表達式目錄樹:
Action<object> anAction = o => { Console.WriteLine(o); };
Func<object, int> aFunc = o =>
{
var s = (o ?? "").ToString();
Console.WriteLine(s);
return s.Length;
};
C#語言規範(有點令人困惑)使用術語「匿名函數」來涵蓋lambda表達式和匿名方法。匿名函數可以隱式轉換爲兼容的委託類型,方法組也可以。因此,如果我們有一個稱爲DelegateType
委託類型,並且像這樣的聲明/分配:
DelegateType d = [something];
然後[something]
可以是方法基或匿名函數。換句話說,它可以是方法組,匿名方法或lambda表達式。
所以,你糾正書中的文字將是更好地說:「在地方的方法組」,但我要說的
lambda表達式是一個未命名的方法,如命名的方法組,可以用來創建委託實例。
我也想補充
在某些情況下,lambda表達式可以用來創建一個表達式樹,而不是委託實例。
你對這種微妙的問題有着敏銳的眼光;你說的這句話是不正確的,也是不準確的,即使它得到了正確的想法。如果你仔細閱讀技術書籍,你很快就會發現許多這類問題。例如,即使有經驗的作者也會將「對象」與「變量」混淆起來。我編輯的唯一一本正確使用技術術語的書幾乎每次都是深度_C#。 :-) –
@EricLippert謝謝埃裏克:-) –
Pedantry:在聲明'TransformerDelegate t = SquareMethod;',SquareMethod不是一個方法,它是一個*方法組*。 – phoog