c# - 在 C# 中,为什么匿名方法不能包含 yield 语句?

标签 c# yield anonymous-methods yield-return

我认为做这样的事情会很好(使用 lambda 进行 yield 返回):

public IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new()
{
    IList<T> list = GetList<T>();
    var fun = expression.Compile();

    var items = () => {
        foreach (var item in list)
            if (fun.Invoke(item))
                yield return item; // This is not allowed by C#
    }

    return items.ToList();
}

但是,我发现我不能在匿名方法中使用yield。我想知道为什么。 yield docs就说不允许吧。

由于不允许我创建列表并将项目添加到其中。

最佳答案

Eric Lippert 最近写了一系列关于为什么在某些情况下不允许 yield 的博文。

编辑2:

  • Part 7 (这个是后来发布的,专门解决了这个问题)

你可能会在那里找到答案......


EDIT1:这在 Eric 对 Abhijeet Patel 的评论的回答中的第 5 部分的评论中进行了解释:

问:

Eric,

Can you also provide some insight into why "yields" are not allowed inside an anonymous method or lambda expression

一个:

Good question. I would love to have anonymous iterator blocks. It would be totally awesome to be able to build yourself a little sequence generator in-place that closed over local variables. The reason why not is straightforward: the benefits don't outweigh the costs. The awesomeness of making sequence generators in-place is actually pretty small in the grand scheme of things and nominal methods do the job well enough in most scenarios. So the benefits are not that compelling.

The costs are large. Iterator rewriting is the most complicated transformation in the compiler, and anonymous method rewriting is the second most complicated. Anonymous methods can be inside other anonymous methods, and anonymous methods can be inside iterator blocks. Therefore, what we do is first we rewrite all anonymous methods so that they become methods of a closure class. This is the second-last thing the compiler does before emitting IL for a method. Once that step is done, the iterator rewriter can assume that there are no anonymous methods in the iterator block; they've all be rewritten already. Therefore the iterator rewriter can just concentrate on rewriting the iterator, without worrying that there might be an unrealized anonymous method in there.

Also, iterator blocks never "nest", unlike anonymous methods. The iterator rewriter can assume that all iterator blocks are "top level".

If anonymous methods are allowed to contain iterator blocks, then both those assumptions go out the window. You can have an iterator block that contains an anonymous method that contains an anonymous method that contains an iterator block that contains an anonymous method, and... yuck. Now we have to write a rewriting pass that can handle nested iterator blocks and nested anonymous methods at the same time, merging our two most complicated algorithms into one far more complicated algorithm. It would be really hard to design, implement, and test. We are smart enough to do so, I'm sure. We've got a smart team here. But we don't want to take on that large burden for a "nice to have but not necessary" feature. -- Eric

关于c# - 在 C# 中,为什么匿名方法不能包含 yield 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1217729/

相关文章:

c# - 在 C# 中嵌入 IronPython

javascript - 从从数组创建的生成器列表中产生

function - 如何将另一个函数返回的函数分配给函数变量?结果而不是生成函数本身

c# - 匿名方法作为 BeginInvoke 的参数?

delphi - 在Delphi匿名方法中不能使用var参数吗?

c# - ExpanderView 在页面导航后展开

c# - 将视频上传到 YouTube - 超出配额错误

c# - 在 ASP.NET Web 应用程序中隐藏查询字符串

python - 为什么 print ("text {}".format(yield i)) 是无效的语法,而 print ("text {}".format((yield i))) 是有效的?

java - 如何从 API 端点按需使用数据库逐个获取的 yield 结果?是否需要网络套接字?