【问题标题】:'Yield' in either IEnumerator or IEnumerable?IEnumerator 或 IEnumerable 中的“产量”?
【发布时间】:2019-02-27 22:54:23
【问题描述】:

我一直在寻找这一点,但我还没有得到任何关于它的信息!。

我看了很多关于“收益回报”的视频和红色文章,我想我对此有了更好的理解,但有一点我无法理解

什么是正确的接口,我应该在其中使用 yield return 吗? (当然 Yield 返回会在 Loop 中使用,但在哪个界面中使用)。

我的意思是在这一点上有所不同,我看到一些人在IEnumerator 中创建了一个“迭代器”,例如:

static string[] Names = { "Name1", "Name2", "Name3" };

    static IEnumerator Test()
    {
        for (int i = 0; i < Names.Length; i++)
        {
            yield return Names[i];
        }
    }

还有一些人使用IEnumerable:

        static IEnumerable Test()
    {
        for (int i = 0; i < Names.Length; i++)
        {
            yield return Names[i];
        }
    }

我假设最好在IEnumerable 接口中使用“Yield return”创建一个“Iterator”,因为通常 IEnumerable 负责访问该类(更准确地说,它返回该类的一个实例(Object)) 捍卫迭代的逻辑。以及在这种情况下编译器(yield 关键字的糖)究竟发生了什么。

 private static IEnumerable Test() => new <Test>d__1(-2);
//decompiled code of Test() method above Using reflector tool

对此有什么想法吗?

【问题讨论】:

  • 返回IEnumerable,而不是IEnumerator。所有 linq 扩展方法都使用IEnumerable。
  • 当你想要一种非标准的枚举方式时,你只需要定义一个IEnumerator。您的Test 方法应该返回一个IEnumerable,可以使用foreach 循环枚举。

标签: c# iterator yield-return


【解决方案1】:

编译器支持两者,实际上如果返回值为IEnumerable&lt;T&gt;,生成的类将实现GetEnumerator() 实现的两个接口(大致):

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    if (state == Created && initialThreadId == Environment.CurrentManagedThreadId)
    {
        state = EnumerationStarted;
        return this;
    }
    else
        return new GeneratedEnumerableEnumerator(state: EnumerationStarted);
}

上面代码中的state 是int,Created 和EnumerationStarted 不是真正的常量名称。 state 可以有许多内部值,具体取决于实现的复杂性。

我应该使用yield return的正确接口是什么

这取决于你的情况。如果您在自定义集合类型中实现IEnumerable&lt;T&gt;.GetEnumerator(),请使用IEnumerator&lt;T&gt;。如果您需要返回一个IEnumerable&lt;T&gt;,其内容可以很容易地产生,那么使用IEnumerable&lt;T&gt;。两者都有道理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 2016-08-24
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多