Okay, let's start with this very simple button click method
private void button1_Click(object sender, EventArgs e)
{
int counter = 1;
List<int> items = new int[] { 1, 2, 3 }.ToList();
List<int>.Enumerator enm = items.GetEnumerator();
// 1
if (!enm.MoveNext())
throw new Exception("Unexpected end of list");
if (enm.Current != counter)
throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
counter++;
// 2
if (!enm.MoveNext())
throw new Exception("Unexpected end of list");
if (enm.Current != counter)
throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
counter++;
//3
if (!enm.MoveNext())
throw new Exception("Unexpected end of list");
if (enm.Current != counter)
throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
counter++;
if (enm.MoveNext())
throw new Exception("Unexpected continuation of list");
}
This method do nothing because every assertion gracefully pass. Things are fine until I believe I should introduce a method to remove redundancy
static void AssertNext(ref int counter, List<int>.Enumerator e)
{
if (!e.MoveNext())
throw new Exception("Unexpected end of list");
if (e.Current != counter)
throw new Exception(String.Format("Expect {0} but actual {1}", counter, e.Current));
counter++;
}
private void button2_Click(object sender, EventArgs e)
{
var counter = 1;
var items = new int[] { 1, 2, 3 }.ToList();
var enm = items.GetEnumerator();
AssertNext(ref counter, enm);
AssertNext(ref counter, enm);
AssertNext(ref counter, enm);
if (enm.MoveNext()) throw new Exception("Unexpected continuation of list");
}
Even though, this refactoring is straightforward (for me, at least). It does break the program ! On the second call to AssertNext, it seems like the enumerator was already reset to the starting point and cause the assertion to fail.
I cannot understand what happen. I really feel like a beginner with this puzzle.
What I miss here ?
I'm imagining it has something to do with List.Enumerator being a struct. You're passing it to a method, manipulating it, and then returning. The manipulation will probably not have happened for your original instance.
List<T>.Enumerator
is a value type meaning that it's copied into the local scope of your method, altered, and then destroyed upon leaving the method. Try passing it by reference too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With