It is actually quite obvious, but figuring out the implications still took me a few minutes today.
Suppose you have a simple list of objects:
And for some reasons you’d like to create a projection from this list using a wrapper class. One reason why you would do this is wrapping business objects into ViewModels.
The Wrapper class only adds the capability of being flagged to the whole story:
So what you now have in enumerable is an IEnumerable<Wrapper>. Next, you’d like to use the wrapper functionality and flag the two elements in enumerable:
And then you go forth using your enumerable, only to discover that none of the contained elements are flagged.
It’s because an IEnumerable is not a List. One needs to understand that prior to calling .ToList() or using foreach() to enumerate over it, no constructor of wrapper has been invoked. Put another way, only because we used this nifty LINQ projection, no Wrapper instances exist yet.
They came into life when we foreach’ed them and disappeared right after that. Whenever we try to use enumerable again, we are enumerating this LINQ expression again. Which means we call the constructors again and we get totally different instances of Wrapper.
For example, suppose we’d use this expression in order to check how many elements are actually selected as an effort to find out why the program doesn’t work as expected:
This will return 0, as we already know. The best way to find out is to step through the provided code and put a breakpoint into the Wrapper constructor. Please find the whole source code ready for copy & paste at the end of this article.
Although i knew how an IEnumerable behaves, it took me 10 minutes today to find my error in a slightly more complicated example. I guess it’s the special case of using a linq projection together with an IEnumerable that got me.