在IEnumerator或IEnumerable中,“Yield”是什么意思?

7

我一直在寻找关于这个问题的信息,但是还没有找到任何有用的资料!

我看了很多关于“Yield Return”的视频和文章,我认为我对它有了更好的理解,但是有一个问题我还是不太明白。

在哪个接口中应该使用yield return?(当然,yield return将在循环中使用,但是在哪个接口中呢?)

我的意思是,在这个问题上有一些变化。例如,我看到有些人在IEnumerator中创建一个"iterator"

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”创建“迭代器”更好,因为一般情况下,IEnumerable负责访问类(更准确地说,它返回一个类(对象)的实例),该类维护迭代逻辑。编译器会在这种情况下(使用yield关键字的语法糖)实现这一点。

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

有关这个的任何想法吗?

返回 IEnumerable,而不是 IEnumerator。所有的 Linq 扩展方法都使用 IEnumerable - FCin
只有在需要非标准枚举方式时才需要定义 IEnumerator。您的 Test 方法应返回一个可使用 foreach 循环枚举的 IEnumerable - mm8
1个回答

4
编译器支持这两种方式,实际上如果返回值是 IEnumerable<T>,生成的类将会同时实现这两个接口,其中 GetEnumerator() 的实现大致如下:
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
    if (state == Created && initialThreadId == Environment.CurrentManagedThreadId)
    {
        state = EnumerationStarted;
        return this;
    }
    else
        return new GeneratedEnumerableEnumerator(state: EnumerationStarted);
}

在上面的代码中,state 是一个 int 类型,CreatedEnumerationStarted 不是真正的常量名称。根据你的实现复杂度,state 可以有许多内部值。

我应该使用哪个正确的接口来使用 yield return?

这取决于你的情况。如果你在自定义集合类型中实现了 IEnumerable<T>.GetEnumerator(),则使用 IEnumerator<T>。如果你需要返回一个可以轻松使用 yield 的 IEnumerable<T>,则使用 IEnumerable<T>。两者都可以有意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接