IEnumerable does not guarantee that enumeration will give the same result twice. In fact, it’s quite simple to create an example in which myEnumerable.First()
returns two values when executed twice:
class A { public A(string value) { Value = value; } public string Value {get; set; } } static IEnumerable<A> getFixedIEnumerable() { return new A[] { new A("Hello"), new A("World") }; } static IEnumerable<A> getDynamicIEnumerable() { yield return new A("Hello"); yield return new A("World"); } static void Main(string[] args) { IEnumerable<A> fix = getFixedIEnumerable(); IEnumerable<A> dyn = getDynamicIEnumerable(); Console.WriteLine(fix.First() == fix.First());
This is not just an academic example: using the popular from ... in ... select new A(...)
will create just this situation. This may lead to unexpected behavior:
fix.First().Value = "NEW"; Console.WriteLine(fix.First().Value); // prints NEW dyn.First().Value = "NEW"; Console.WriteLine(dyn.First().Value); // prints Hello
I understand why this is happening. I also know that this could be fixed by doing ToList()
in Enumerable or overriding ==
for class A
This is not my question.
The question is: when you write a method that takes an arbitrary IEnumerable, and you want the property to be evaluated only once (and then the links are “fixed”), what is the canonical way to do this? ToList()
apparently used mainly, but if the source is already fixed (for example, if the source is an array), the links are copied to the list (unnecessarily, since all I need is a fixed property). Is there something more appropriate or ToList()
"canonical" solution for this problem?
source share