score:6

Accepted answer

the first block of code builds the items once and returns a list with the items.

the second block of code builds those items each time the ienumerable is walked through.

this means that the second and third line of the first block operate on the same object instance. the second block's second and third line operate on different instances of foo (new instances are created as you iterate through).

the best way to see this would be to set breakpoints in the methods and run this code under the debugger. the first version will only hit the breakpoint once. the second version will hit it twice, once during the .where() call, and once during the .elementat call. (edit: with the modified code, it will also hit the breakpoint a third time, during the tolist() call.)

the thing to remember here is that an iterator method (ie. it uses yield return) will be run every time the enumerator is iterated through, not just when the initial return value is constructed.

score:0

suggestion: compile the code and open with reflector. yield is a syntactical suger. you would be able to see the code logic difference in the code your wrote and the code generated for the yield keyword. both are not the same.

score:1

listtwo is an iterator - a state machine.

elementat must start at the beginning of the iterator to correctly get the i-th index in the ienumerable (whether or not it is an iterator state machine or a true ienumerable instance), and as such, listtwo will be reinitialized with the default values of enabled = true for all three items.

score:2

those are definitely not the same thing.

the first builds and returns a list the moment you call it, and you can cast it back to list and list-y things with it if you want, including add or remove items, and once you've put the results in a variable you're acting on that single set of results. calling the function would produce another set of results, but re-using the result of a single call acts on the same objects.

the second builds an ienumerable. you can enumerate it, but you can't treat it as a list without first calling .tolist() on it. in fact, calling the method doesn't do anything until you actually iterate over it. consider:

var foolist = data.list2().where(f => f.id > 1);
// no foo objects have been created yet.
foreach (var foo in foolist)
{
   // a new foo object is created, but not until it's actually used here
   console.writeline(foo.enabled.tostring());  
}

note that the code above will create the first (unused) foo instance, but not until entering the foreach loop. so the items aren't actually created until called for. but that means every time you call for them, you're building a new set of items.


Related Query

More Query from same tag