LINQ and IEnumerable may surprise you
Let us examine the following code snippet:
class Candidate
{
public string Name { get; set; }
public bool Hired { get; set; }
}
class Program
{
static void Main(string[] args)
{
string[] names = { "Adam", "Byron", "Charles" };
var candidates = names.Select(n => new Candidate()
{
Name = n,
Hired = false
});
//now modify the value of each object
foreach (var candidate in candidates)
{
candidate.Hired = true;
}
//noew print the value of each object
foreach (var candidate in candidates)
{
Console.WriteLine(string.Format("Name:{0} Hired:{1}",
candidate.Name, candidate.Hired));
}
Console.Read();
}
}
Basically, I create an IEnumerable<Candidate> from LINQ, and them loop through the results to modify each object. At the end, you might expect each candidate hired. Wrong! Here is the output:
What happened was LINQ actually delayed the object generation until enumeration. When we enumerate again to print the objects, LINQ actually generated a new set of objects. If you use ToList() to convert the IEnumerable to List, you will get the expected result:
var candidates = names.Select(n => new Candidate()
{
Name = n,
Hired = false
}).ToList();
ToList() will instantiate the objects immediately and the subsequent enumeration will be on the same objects. That is why you cannot find the .ForEach() extension method on IEnumerable<T>. You have to convert it to IList<T> to use the method.