簡體   English   中英

為什么lambdas需要=>作為語法的一部分?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM