您可以访问IEnumerable吗?

jb.*_*jb. 6 c# ienumerable yield-return

我的下面的代码number通过创建素数列表并检查下一个潜在素数是否可被列表中的任何素数整除,来查找下面的所有素数.

我正在努力学习它的来龙去脉yield return.现在我有一个List<int> primes我在函数内部使用的.但我正在返回相同的数据yield return.所以我的问题是

我可以在创建函数时从函数内部访问IEnumerable <int>吗?所以我可以完全删除List <int> primes.

/// <summary>
/// Finds all primes below <paramref name="number"/>
/// </summary>
/// <param name="number">The number to stop at</param>
/// <returns>All primes below <paramref name="number"/></returns>
private static IEnumerable<long> PrimeNumbers(long number)
{
    yield return 2;
    List<long> primes = new List<long>(2);          

    for(long num = 3; num < number; num += 2)
    {

        //if any prime lower then num divides evenly into num, it isn't a prime
        //what I'm doing now
        if(!primes.TakeWhile(x => x < num).Any(x => num % x == 0))
        {
            primes.Add(num);
            yield return num;
        }

        //made-up syntax for what I'd like to do
        if(!this.IEnumerable<long>
                .TakeWhile(x => x < num).Any(x => num % x == 0))
        {
            yield return num;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 4

不,你不能那样做。编译器构建一个状态机来实现yield return,并且通过可枚举进行枚举的调用代码与您的代码一样是其工作的一部分。编译器构建一个隐藏对象来存储代码的当前状态,包括其调用堆栈和局部变量,并且当调用者调用Current和时,它会调用方法的不同部分MoveNext。在另一个枚举正在进行时尝试从头开始枚举对象会扰乱正在进行的枚举,这并不是一件好事。

在这种特殊情况下,您也不希望发生这种情况: 的实现yield return不存储您生成的值,因此即使您可以IEnumerable在枚举时访问自己的值,它也会多次递归地回调自身以生成每个值新项目,因此即使产生中等数量的素数,也需要花费相当长的时间。