![](/img/trans.png)
[英]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.