I have a problem with my iterator in C# which I can't seem to resolve. Here are the two relevant methods (simplified for the purposes of the question):
protected virtual IEnumerable<T> Iterator()
{
// Code here omitted for brevity
foreach(object row in compiler.ResultsIterator())
{
Model obj;
object[] row_array = new object[fields_length];
// Logic to set row_array values omitted for brevity
obj = _model.Clone(); // Does a MemberwiseClone
obj.SetFieldValues(row_array);
yield return (T)(obj as object);
}
}
private void FillCache()
{
IEnumerator<T> _iter = Iterator().GetEnumerator();
while(_iter.MoveNext())
{
ResultCache.Add(_iter.Current);
}
}
The issue is that on the first iteration in FillCache() ResultCache contains an object, let's call it 'Object 1' but on the second iteration it contains 'Object 2' twice. Clearly the problem is that the variable 'obj' is passed by reference and is not being created new even though it is declared inside the foreach loop.
So my question is how can I create a new 'obj' reference each time?
Ok, I feel bad about misleading with the yield problem but the issue is a question of references. It turns out the real problem is the MemberwiseClone because this is only a shallow copy so all the deep member references are the same.
Therefore the answer is that the Clone() method should perform a deep copy.