我是编程新手,并且一直在尝试编写一些随机函数。

我写了下面的函数,它基于eratosthenes筛子松散地工作。但是最初,我对updatedEntries IEnumerable遇到了问题。

updatedEntites有点填充(与我收集的延迟执行有关–在调试模式下,“ current”为null,但结果视图包含相关项),但是当RemoveWhere应用于oddPrimesAndMultiples时,即使我删除了updatedEntries中的项,没有看到为什么它们仍应链接到oddPrimesAndMultiples中的项目。 (我可能只是完全误解了正在发生的事情,而问题可能完全是另外一回事!)

如果我将updatedEntries更改为List而不是IEnumerable,则不会出现此问题,而实际上我现在已经重写了该语句,而没有使用LINQ来(可能吗?)更好地利用我无论如何都使用SortedSet的事实。但我仍然想知道为什么这个问题首先出现!

这是我的代码:

public static IEnumerable<int> QuickPrimes()
        {
            int firstPrime = 2;
            int firstOddPrime = 3;

            int currentValue = firstOddPrime;
            int currentMinimumMultiple;

            SortedSet<Tuple<int, int>> oddPrimesAndMultiples = new SortedSet<Tuple<int, int>>() { new Tuple<int, int> (firstOddPrime, firstOddPrime) };
            IEnumerable<Tuple<int, int>> updatedEntries;

            yield return firstPrime;
            yield return firstOddPrime;

            while (true)
            {
                currentMinimumMultiple = oddPrimesAndMultiples.First().Item1;
                while (currentValue < currentMinimumMultiple)
                {
                    yield return currentValue;
                    oddPrimesAndMultiples.Add(new Tuple<int, int> (currentValue * 3, currentValue));
                    currentValue += 2;
                }

                updatedEntries = oddPrimesAndMultiples.Where(tuple => tuple.Item1 == currentMinimumMultiple)
                                                        .Select(t => new Tuple<int, int>(t.Item1 + 2 * t.Item2, t.Item2));

                oddPrimesAndMultiples.RemoveWhere(t => t.Item1 == currentMinimumMultiple);
                oddPrimesAndMultiples.UnionWith(updatedEntries);
                currentValue += 2;
            }
        }


而我正在测试功能的主要地方:

static void Main(string[] args)
        {
            foreach(int prime in Problems.QuickPrimes())
            {
                Console.WriteLine(prime);
                if (prime > 20) return;
            }
        }


提前谢谢了!

最佳答案

陷阱是updatedEntries在一行中定义,但实际上在以后执行。

为了使它回归基础,请参见以下代码片段(来自Linqpad):

var ints = new SortedSet<int>( new[] { 1,2,3,4,5,6,7,8,9,10});

var updatedEntries = ints.Where(i => i > 5); // No ToList()!
updatedEntries.Dump();


这显示6, 7, 8, 9, 10

ints.RemoveWhere(i => i > 7);
updatedEntries.Dump();


现在显示6, 7,因为updatedEntries被重新执行。

ints.UnionWith(updatedEntries);


这会添加6, 7,而您希望它会添加第一个列表6, 7, 8, 9, 10

因此,在定义IEnumerable时,您应该始终知道它的实际执行时间。它始终在该特定点作用于程序的状态。

关于c# - IEnumerable项目在使用LINQ之前消失了,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42170754/

10-12 02:55