2013-02-19 59 views
2

请考虑下面的C#块:如何避免Iterator方法重新启动?

int resultIndex = 0; 

Result firstResult = results.First(); 
DoAVeryImportOperationWithFirstResult(firstResult); 

Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
yield return firstResult; 

foreach(Result result in results) 
{ 
    Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
    yield return result; 
} 

如果您正在使用LINQ和迭代熟悉,你会发现,在foreach块的第一次迭代,从结果的第一个结果将被替代返回的第二个。

所以,基本上这是我的问题:我无法从迭代器方法获取第一个值,然后在不重新启动此方法的情况下在其他位置使用它。

有人知道这方面的一些解决方法?

回答

7

其他人已经显示了使用foreach循环和条件执行的方法。这实际上是一个整洁的方法 - 但这是另一种选择,以防因任何原因foreach循环不合适。

using (var iterator = results.GetEnumerator()) 
{ 
    if (!iterator.MoveNext()) 
    { 
     // Throw some appropriate exception here. 
    } 

    Result firstResult = iterator.Current; 
    DoAVeryImportOperationWithFirstResult(firstResult); 

    Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
    yield return firstResult; 

    while (iterator.MoveNext()) 
    { 
     Result result = iterator.Current; 
     Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
     yield return result; 
    } 
} 
+1

该死!再次击败它。 – 2013-02-19 22:09:39

3

只要做到这一点明确:

bool first = true; 
foreach(var item in results) { 
    if(first) { 
     first = false; 
     // whatever 
    } else { 
     // whatever else 
    } 
} 

或更复杂:

using(var iter = results.GetEnumerator()) { 
    if(iter.MoveNext()) { 
     // do first things with iter.Current 

     while(iter.MoveNext()) { 
      // do non-first things with iter.Current 
     } 
    } 
} 
3

您需要手动迭代:

var enumerator = results.GetEnumerator(); 
enumerator.MoveNext(); 
yield return enumerator.Current; //first 
while(enumerator.MoveNext()) 
yield return enumerator.Current; //2nd, ... 

检查省略所有的错误......也不要” t忘记处置。

2

您需要使用跳过

foreach(Result result in results.Skip(1)) 
{ 
    Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
    yield return result; 
} 

或手动遍历结果。

如果你想想如何迭代器实现的是哪个,你所看到的确实是预期的行为!

+1

请注意,这样做包括迭代源序列两次。在许多实际情况下,这很好,但在一般情况下并非如此。 – Servy 2013-02-19 22:11:24

3
bool isFirst = true; 
foreach(Result result in results) 
{ 
    if(isFirst) 
    { 
     DoAVeryImportOperationWithFirstResult(firstResult); 
     isFirst = false; 
    } 

    Console.WriteLine(String.Format("This is the {0} result.", resultIndex++)); 
    yield return result; 
}