...为什么是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# 语言的设计原则。节省几次击键的好处不值得痛苦违反了代码中明确说明意图的设计原则。
(*) Like implicitly typed locals, method type inference, implicitly typed arrays, and overload resolution, all of which involve the compiler making a best guess as to what the developer intended. The rules for making those guesses are carefully documented and have been designed so that most will bail out early if any ambiguity is detected.