繁体   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