【问题标题】:Is it possible to return a list from an iterator block?是否可以从迭代器块返回列表?
【发布时间】:2014-11-27 21:23:11
【问题描述】:

我有这个功能:

class Path : List<LineSegment> { }

private IEnumerable<LineSegment> GetLineSegments(CollisionType collisionType, Path path)
{
    if (collisionType == CollisionType.End)
    {
        yield return path.First();
        yield return path.Last();
    }
    else if (collisionType == CollisionType.Segment)
    {
        foreach (LineSegment lineSegment in path)
        {
            yield return lineSegment;
        }
    }
}

基本上,我以两种方式检查碰撞(球和线之间)。在一种情况下,我只想检查绘制路径的端点,但在另一种情况下,我想返回整个路径中的每个线段。

循环遍历给定列表只是为了返回整个列表似乎有点奇怪。我可以只返回列表吗?我希望能够做这样的事情,但我得到了错误:

private IEnumerable<LineSegment> GetLineSegments(CollisionType collisionType, Path path)
{
    if (collisionType == CollisionType.End)
    {
        yield return path.First();
        yield return path.Last();
    }
    else if (collisionType == CollisionType.Segment)
    {
        return path.AsEnumerable<LineSegment>();
    }
}

【问题讨论】:

    标签: c# linq ienumerable yield


    【解决方案1】:

    您别无选择,只能使用foreach 循环。这是一项经常被请求的功能,但不是该语言。

    【讨论】:

    • 好的,谢谢,反正我还有一个选择。 IEnumerable&lt;LineSegment&gt; segments = collisionType == CollisionType.Segment ? path : new List&lt;LineSegment&gt;() { path.First(), path.Last() }; 可能更干净所以一切都很好。
    • @JohnSmith 请注意,这在语义上是不同的。由于这不是迭代器块,因此代码会被急切地执行,而不是被推迟到迭代器被枚举。如果你不在乎,没关系,只要意识到这两者不是一回事。
    • 是的,这对我来说并不重要,但很高兴为未来的读者指出。
    • 这是一个要求的功能,但这样做会非常困难(因为该死的几乎是不可能的)。当您使用“yield return”时,它从根本上改变了编译器解析和编译该方法的方式。事实上,在幕后,它基本上创建了一个实现 IEnumerable 的私有类,并使用一些魔法在其中对该方法进行编码,以复制行为就好像该函数在'收益回报'。
    • @CleverNeologism 这根本不是不可能的。事实上,这样做相当简单。语法可能需要不同,yield foreach &lt;sequence of things to yield&gt; 的使用是一种经常使用的建议,这将确保词法分析器/解析器不会出现问题。至于实现,它几乎只是将其重构为这里的内容,创建一个循环并产生其中的每个项目。它可能会带来一些没有语言功能就无法实现的性能优化,这也是拥有它的部分原因。
    猜你喜欢
    • 1970-01-01
    • 2011-04-02
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    • 2015-07-23
    • 1970-01-01
    • 2012-12-07
    相关资源
    最近更新 更多