What would be the output of the following program;
var xs = new int[]{1,2,3}; Observable.Generate( xs.GetEnumerator(), // initial state e => e.MoveNext(), // break condition e => e, // iterate e => e.Current // result selector ).Subscribe(Console.WriteLine);
The program (correctly) outputs;
1
2
3
What about this program? Would the output be the same? If not why not?
var xs = new List<int>{1,2,3};
Observable.Generate( xs.GetEnumerator(), // initial state e => e.MoveNext(), // break condition e => e, // iterate e => e.Current // result selector ).Subscribe(Console.WriteLine);
Stay tuned.




October 26, 2011 at 4:29 pm
The List returns a value type implementing the enumerator whereas the array returns a reference type. This means that when the enumerator is shuffled around inside the Observable.Generate logic, it is copied and/or passed by value between the three lambdas.
The array enumerator exhibits the intuitively “correct” behavior and if you want the same behavior from the list, you will have to box the enumerator thusly: (IEnumerator)xs.GetEnumerator()
October 26, 2011 at 4:53 pm
Cathal, Niall and I think we figured this one out…….
List+Enumerator is a struct, so is therefore copied by value in your Generate method. If you cast your xs to IEnumerable you will get it back as an IEnumerator which means it is boxed and so there fore treated as a reference type moving forward…..? Thus, you are manipulating the same copy each time (the boxed version sitting on the heap).
var xs = new List{1,2,3};
Observable.Generate(
((IEnumerable)xs).GetEnumerator(), // initial state
e => e.MoveNext(), // break condition
e => e, // iterate
e => e.Current // result selector
).Subscribe(Console.WriteLine);
October 26, 2011 at 4:57 pm
2x correct answers!