Reputation: 13260
Please consider the following C# block:
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;
}
If you are familiarized with Linq and Iterators, you'll notice that in the first iteration of the foreach
block, the first result from results will be returned instead of the second one.
So, basically this is my problem: I can't get the first value from the iterator method then use it somewhere else without restarting this method.
Someone know some workaround for this?
Upvotes: 2
Views: 121
Reputation: 1502656
Others have shown the approach using a foreach
loop and conditional execution. That's actually a neat approach - but here's another option in case the foreach
loop is inappropriate for whatever reason.
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;
}
}
Upvotes: 7
Reputation: 33381
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;
}
Upvotes: 3
Reputation: 55750
You need to use Skip
foreach(Result result in results.Skip(1))
{
Console.WriteLine(String.Format("This is the {0} result.", resultIndex++));
yield return result;
}
or manually iterate over the results.
If you think about how iterators are implemented what you are seeing is indeed the expected behavior!
Upvotes: 2
Reputation: 171216
You need to iterate manually:
var enumerator = results.GetEnumerator();
enumerator.MoveNext();
yield return enumerator.Current; //first
while(enumerator.MoveNext())
yield return enumerator.Current; //2nd, ...
All error checking omitted... Also don't forget to dispose.
Upvotes: 3
Reputation: 1063704
Just do it explicitly:
bool first = true;
foreach(var item in results) {
if(first) {
first = false;
// whatever
} else {
// whatever else
}
}
or more complex:
using(var iter = results.GetEnumerator()) {
if(iter.MoveNext()) {
// do first things with iter.Current
while(iter.MoveNext()) {
// do non-first things with iter.Current
}
}
}
Upvotes: 3