当你可以在lambda中使用await时,为什么不能在lambda中使用yield?

jak*_*sch 25 c# iterator yield-return async-await

根据Eric Lippert的说法,匿名迭代器没有被添加到语言中,因为实现它会过于复杂.

这对我来说没关系,在他们继续实施匿名异步方法之前,它并没有打扰我.编译器必须对异步方法执行与迭代器相同的操作(将它们转换为状态机),所以我很困惑为什么匿名迭代器也不允许,当匿名异步方法时.

有人可以对此有所了解吗?

Eri*_*ert 25

根据Eric Lippert的说法,匿名迭代器没有被添加到语言中,因为实现它会过于复杂.

这不正是我打算传达的.相关成本是实现成本,是的,但它是现有编译器中的实现成本,其在架构上未设置以实现该复杂功能.

编译器必须对异步方法执行与迭代器相同的操作(将它们转换为状态机),所以我很困惑为什么匿名迭代器也不允许,当匿名异步方法时.

简短的历史是相关的.C#首先在C#2.0中使用了匿名方法和迭代器块.当我在C#3.0中添加lambdas时,重构所有现有的匿名方法代码是一项重大成本,因此它可以处理lambdas的所有新功能.这使得修改变得更加复杂和昂贵.制造迭代器阻挡lambdas的成本太高,无法产生的收益; 它将占总成本的很大一部分.我们负担不起.如果你在Developer Division的工作时间表中加入了每个团队,那么"最长极"的团队就是C#3.0编译团队,而我在语义分析器上的工作是IIRC,它是编译器团队中最长的一个.每天我们可能都会放弃C#3.0,这可能是Visual Studio可能会滑落的一天.因此,任何没有使LINQ更好的东西都被削减了,其中包括迭代器lambda.

在C#4中,迭代器lambdas是许多被考虑的特征之一.我们有一个潜在的良好功能列表,比你的手臂更长,我们可以负担不到十分之一.

在C#5中,团队添加了异步方法.设计和实现团队长期尝试提出一个底层抽象,它对迭代器块和等待重写都很常见; 你注意到它们显然是相似的.但最终,找到一般解决方案的成本并不能为此付出代价.普遍性是非常昂贵的,并且发现一般性,即设计只统一件事是愚蠢的,如果它不便宜.

因此决定将await rewriter作为自己的东西来实现.鉴于该团队将承担这笔巨额费用,并且鉴于异步方法的原始转换无论如何都将变为lambda形式,因此决定投资于完整功能:包含lambdas的异步方法,async lambdas包含lambdas,整个交易.该功能的成本只是整个功能成本的一小部分,这非常昂贵.

再说一次,我们遇到长杆问题.await应该避免在lambda引擎上可能有不稳定的任何工作,包括尝试使它们与迭代器块一起工作.

现在比较Visual Basic.VB很长一段时间都没有迭代器块.添加它们后,没有现有的基础设施可以继续工作!整个过程可以从头开始构建,以处理包含lambda和包含迭代器块的lambda的迭代器块,这样就完成了.

C#编译器已通过Roslyn项目彻底重新构建和重写.我希望这将降低在假设的未来版本的C#中实现迭代器块lambdas的成本.我们会看到的!

  • @Janiels:简而言之:代码重用实际上很少是您认为的节省.通常情况下,更好地利用有限的资源来制作两个相似的东西,每个东西都做得很好,并且可以随意修改而不影响其他东西,而不是让一件事做得恰到好处.罗斯林团队在几个月内进行了这场辩论:我们应该有一个编译器可以编译C#和VB,还是两个编译器,每个编译器都能很好地编译一种语言*并且可以在以后单独更改*?我们选择后者. (2认同)

Ser*_*rvy 5

匿名迭代器块虽然不错,但没有特别引人注目的好处.迭代器块被重构为自己的方法并不是一个巨大的威慑.

async匿名方法做了很多概念的意义上,不保证重构到自己的方法以同样的方式匿名迭代器块做的,有很多更引人注目的终端用户受益.

简而言之,与迭代器块不同,这些好处值得付出代价.成本可能相当可比.