2017-02-11 4 views
3

저는 프로그래밍에 익숙하지 않고 임의의 기능을 작성하고 놀고 있습니다.IEnumerable 항목이 LINQ를 사용하여 사용되기 전에 사라졌습니다.

필자는 eratosthenes sieve를 기반으로 느슨하게 작동하는 아래 기능을 작성했습니다. 처음에는 updatedEntries IEnumerable에 문제가있었습니다.

updatedEntites가 일종의 채우기 형식이었습니다 (디버그 모드에서 '현재'는 null이지만 결과 뷰에는 관련 항목이 포함되어 있음). 그러나 RemoveWhere가 oddPrimesAndMultiples에 적용되면 updatedEntries oddPrimesAndMultiples의 항목과 왜 여전히 연결되어야하는지 나는 알지 못하더라도 사라졌습니다. (나는 완전히 당황하고있는 일을 완전히 오해 할 수 있으며, 문제는 완전히 다른 것일 수도 있습니다!)

updatedEntries를 IEnumerable이 아닌 List로 변경하면 실제로 문제가 발생하지 않습니다. 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; 
      } 
     } 

많은 감사

여기 내 코드입니다!

+0

yield 키워드를 사용하는 IEnumerable은 실제로 매우 다른 결과를 제공 할 수 있습니다. 그것을 현명하게 사용하십시오. –

+0

내가 이것을 이해했는지 보자. 지금 제시 한 코드가 작동하지만 이전에 updatedEntries 할당에서 ".ToList()"호출을하지 않았기 때문에 이전 버전과 다릅니다. –

+0

문제를 [MCVE]에게 제공해 주시겠습니까? 현재 게시물을 통해 코드에 대해 이야기하는 문제가 있는지 여부는 명확하지 않습니다. –

답변

1

트랩은 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을 보여줍니다. updatedEntries가 다시 실행되기 때문에

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

지금 이것은 6, 7 나타낸다. 첫 번째 목록 6, 7, 8, 9, 10를 추가 할 것으로 예상하면서

ints.UnionWith(updatedEntries); 

이, 6, 7을 추가합니다.

따라서 IEnumerable을 정의 할 때 언제 실제로 실행되는지 알고 있어야합니다. 그것은 항상 특정 지점에서 프로그램의 상태에 따라 작동합니다.