[英]Why do Linq lambdas not require a `return` statement, but mine do?
[英]Why do lambdas require => as part of their syntax?
我在一本書中遇到了這行代碼:
var data = db.Query(sql).OrderByDescending(c => c.DatePosted);
這種事情似乎跟我追尾......
為什么 c => c.
必要? 以下是不可理解的(編譯器,人類更是如此)?
var data = db.Query(sql).OrderByDescending(DatePosted);
我確信在幕后發生了各種奇特的事情,據稱需要這種奇怪的lambda語法,但同樣:
為什么? 真的有必要嗎? 編譯器不能弄清楚DatePosted是要排序的列嗎?
...為什么
c => c.
必要? 以下是不可理解的(由編譯器,甚至人類更是如此......
首先,如果您希望您的查詢可供人類閱讀並刪除lambda,則使用人類可讀的語法編寫查詢並省略lambda:
query = from record in records
orderby record.DatePosted descending
select record;
我更喜歡這種語法的原因:它更容易閱讀,它強調業務領域中查詢的語義,而不是訂購機制需要密鑰選擇功能的事實。
第二, c=>c.
沒有必要。 假設你有一個方法:
static DateTime DatePosted(Record record) { return record.DatePosted; }
現在使用您想要的語法是完全合法的:
records.OrderByDescending(DatePosted)
編譯器將推斷出DatePosted
是調用以獲取排序鍵並適當地構造委托的函數。 (請注意,它也會正確地推斷出類型,並確定您的意思是OrderByDescending<Record, DateTime>
。)
更一般地說:C#的基本設計原則是語言不會猜測你的意思,除非在某些非常明確的情況下(*)。 查詢可以通過任何字面上進行排序,並因此在該代碼的作者感激清楚地說明排序關鍵字是什么。 在查詢語法中,表示集合元素的范圍變量可用,以便您可以輕松地表達“按與每個記錄關聯的日期排序”。 只是說“按日期排序”將涉及進行猜測。
對於lambda語法,該方法需要一個選擇順序鍵的函數。 您可以提供所需的函數,方法是提供委托類型的值,可轉換為委托類型值的lambda,或者可轉換為委托類型值的方法組。 “裸”財產不是一種功能。
因此, 可以在C#語言的設計,這樣當你提供一個屬性的名稱沒有任何上下文解釋什么是它的屬性,編譯器做一個猜測? 它說“哦,我看到這里有一個名為OrderBy的方法,它接受一個函數和一個序列,讓我猜一下,為函數提供的名稱是函數”從給定的元素中取出這個屬性序“嗎? 當然,我可以做到這一點。代碼是不是更難寫。但是,這不會與C#語言的設計原則是一致的。節省幾個按鍵的好處是不值得的痛苦違反設計原則, 意圖在代碼中明確陳述 。
(*)與隱式類型的局部變量,方法類型推斷,隱式類型數組和重載分辨率一樣,所有這些都涉及編譯器最好地猜測開發人員的意圖。 做出這些猜測的規則是經過仔細記錄的,並且經過精心設計,如果檢測到任何歧義,大多數人都會提前紓困。
只編寫DatePosted
本身可能會引用類型,字段,屬性或方法組。 如果它提到的方法組偶然采取了正確的參數類型怎么辦? 那么這會做錯事。
有時,明確並不是一件壞事。 語法
c => c.DatePosted
具體表示接受輸入並返回該輸入的DatePosted
字段/屬性的函數。 這很靈活 - 你可以寫
c => DatePosted(c)
要么
c => c.DatePosted()
要么
c => new DatePosted(c)
取決於你需要做什么。
一些受過教育的猜測在這里,但......
主要是因為“DatePosted”本身沒有內在意義。 它可以是方法,屬性,類型,任何東西。 它也與Func<TSource, TKey>
的方法簽名不匹配,但我假設你的意思是“如果編譯器更聰明”。
但是,您可以傳遞與簽名匹配的內容,如下所示:
public class Foo
{
public int Age {get; set;}
}
public int GetFooAge(Foo f) { return f.Foo; }
var source = <some mess'o Foos>;
source.OrderByDescending(GetFooAge).Dump();
我認為關鍵點在於這樣的特征會對環境造成干擾。 什么是“DatePosted”以及它在何處定義? 編譯器以某種方式處理方法調用,並引入一種特殊的方法調用將是棘手的。 我們怎么知道這應該是一個特殊的方法調用? 為編譯器提供所需的所有上下文更為實用。 這就是為什么簡潔的lambda語法非常有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.