Recently, I had to process a
Collection
of class objects after a split over some properties. I did the split through a relatively simple
Select
and
Distinct
extension methods. The next task was to split the result again in batches and process. I discovered this while doing that. The
ToList
extension method, supposedly, creates a deep copy of the
IEnumerator
returned by the LINQ expression. Following is a simple code to demonstrate.
class Animals
{
public bool Herbivore { get; set; }
public bool IsMammal { get; set; }
public string CommonName { get; set; }
}
private static void SendBatches()
{
Collection<Animals> animalCollection = new Collection<Animals>();
animalCollection.Add(new Animals { Herbivore = true, IsMammal = true, CommonName = "Cow" });
animalCollection.Add(new Animals { Herbivore = false, IsMammal = true, CommonName = "Cat" });
animalCollection.Add(new Animals { Herbivore = false, IsMammal = true, CommonName = "Dog" });
animalCollection.Add(new Animals { Herbivore = true, IsMammal = true, CommonName = "Lamb" });
var herbivores = (from animal in animalCollection
where animal.Herbivore
select new { Name = animal.CommonName, LaysEggs = !animal.IsMammal });
foreach (var herbivore in herbivores)
{
if (herbivore.Name.StartsWith("C", StringComparison.InvariantCultureIgnoreCase))
{
animalCollection.Remove(animalCollection.Where(x => string.Compare(x.CommonName, herbivore.Name, true) == 0).First());
}
}
}
As expected, the
foreach
will fail at the second iteration since we have changed the
Enumerator
. But, if we change the LINQ expression to the following, it works:
var herbivores = (from animal in animalCollection
where animal.Herbivore
select new { Name = animal.CommonName, LaysEggs = !animal.IsMammal }).ToList();
Even
ToArray
gives the same behavior.