With great surprised I observed the following behavior today: Given a class
class Foo
{
prop int FooNumber { get; set; }
}
and this code
IEnumerable<Foo> foos = Enumerable.Range(0,3).Select(new Foo());
foreach (var foo in foos)
foo.Bar = 5;
foreach (var foo in foos)
Console.Write(foo.Bar); // Writes 000
while initializing foos
to new List<Foo>{ new Foo(), new Foo(), new Foo() }
makes the loop write "555".
My question: Why does this happen and is there a way to circumvent this whithout using .ToList()
(which needs a comment, since it does not seem to be needed here).
IEnumerator is the base interface for all non-generic enumerators. Its generic equivalent is the System.
IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. It is the base interface for all non-generic collections that can be enumerated. This works for read-only access to a collection that implements that IEnumerable can be used with a foreach statement.
If we want to implement enumerator logic in any collection class, it needs to implement IEnumerable interface (either generic or non-generic). IEnumerable has just one method whereas IEnumerator has two methods (MoveNext and Reset) and a property Current.
It happens because foos
is dynamically produced each time you enumerate it. So during the first iteration you are setting property values on objects that are no longer referenced by anything after the iteration ends. The second iteration works on freshly constructed objects which have the default property value.
Initializing foos
to a list of "persistent" objects changes things, as does using .ToList()
for the same reason (a "fixed" list is constructed and iterated over twice; the original dynamically produced IEnumerable
is only iterated over once).
Having established that you should use .ToList()
here: in general I do not feel that it needs a comment because it is not customary to iterate over dynamically produced sequences more than once (I believe many code analysis tools warn against this), but by all means do write one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With