是否可以在不使用仅包含C#代码的yield的情况下实现无限的IEnumerable?

时间:2013-11-07 03:27:34

标签: c# ienumerable infinite-loop

修改:显然偏离主题...转移到Programmers.StackExchange.com

这不是一个实际问题,它更像是一个谜语。

问题

我很想知道是否有办法实现与以下相同的东西,但没有使用yield

IEnumerable<T> Infinite<T>()
{
    while (true) { yield return default(T); }
}

规则

  1. 您无法使用yield关键字
  2. 直接使用C#本身 - 没有IL代码,没有构建动态程序集等。
  3. 您只能使用基本的.NET库(仅mscorlib.dllSystem.Core.dll?不确定还包括哪些内容)。但是,如果你找到一些其他.NET程序集(WPF ?!)的解决方案,我也很感兴趣。
  4. 不要实现IEnumerable或IEnumerator。
  5. 注释

    我最接近的是:

    IEnumerable<int> infinite = null;
    infinite = new int[1].SelectMany(x => new int[1].Concat(infinite));
    

    这是“正确的”但是在通过可枚举的14399次迭代之后遇到StackOverflowException(不是很无限)。

    我认为由于CLR的lack of tail recursion optimization,可能无法做到这一点。证明会很好:)

3 个答案:

答案 0 :(得分:5)

  1. 从您的问题中获取yield示例并将其转储到Visual Studio中。
  2. 编译。
  3. 在Reflector / ILSpy / dotPeek / etc中打开。并以C#1.0语言级别显示反编译的源(或切换显示编译器生成的源)。
  4. 宣布胜利,吃蛋糕。

答案 1 :(得分:2)

这是一个几乎无限的迭代器:

using System;
using System.Linq;

public class Test
{
    public static void Main()
    {
        var infiniteIterator =
            Enumerable.Range(Int32.MinValue, Int32.MaxValue)
                      .SelectMany(i => Enumerable.Range(Int32.MinValue, Int32.MaxValue))
                      .SelectMany(i => Enumerable.Range(Int32.MinValue, Int32.MaxValue))
                      .SelectMany(i => Enumerable.Range(Int32.MinValue, Int32.MaxValue))
                      .Select(i => default(int));

        foreach (var infinite in infiniteIterator)
            Console.WriteLine(infinite);
    }
}

答案 2 :(得分:1)

使用IEnumerable<T>yield调用一些C#编译器魔术,它将逻辑包装到IEnumerable的实现中,如下所示:

IEnumerable<T> Infinite<T>() {
    return new Buzzlightyear<T>();
}
private class BuzzLightyear<T> : IEnumerable<T> where T : new() {
    public Boolean MoveNext() { return true; }
    public T Current { return new T(); }
}