Consider the following class:
public class Score
{
private static readonly Guid _relationId = Guid.NewGuid();
public Guid Id { get; set; }
public Guid RelationId { get { return _relationId; } }
public Score()
{
Id = Guid.NewGuid();
}
}
The following function:
public IEnumerable<Score> GetScores()
{
yield return new Score();
yield return new Score();
yield return new Score();
}
Why is it that the following function returns 1:
public int Execute()
{
var scores = GetScores();
IList<Score> externalScores = new List<Score>();
var filteredScores = scores.Where(score => externalScores.All(x => x.RelationId != score.RelationId));
foreach (var score in filteredScores)
{
externalScores.Add(score);
}
return externalScores.Count();
}
But when I add .ToList() to filteredScores (either in the foreach loop or after the linq operation) the result of the function is 3.
I suspect it has something to do with Closing over the loop variable, but I can’t seem to figure this out.
With
ToList, all items inscoresare checked if they match the predicate, which returns always true becauseexternalScoresis empty.Without
ToList, each item inscoresis checked interleaved with theforeachloop (see: Deferred Execution) which modifiesexternalScores, causing the predicate to returntruefor the first item andfalsefor the other two items.