4

好,我们从这个非常简单的按钮点击方法开始

    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");
    }

这个方法什么都不做,因为每个断言都优雅地通过了。一切都很好,直到我相信我应该介绍一种消除冗余的方法

    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");
    }

尽管如此,这种重构还是很简单的(至少对我而言)。它确实破坏了程序!在第二次调用 AssertNext 时,似乎枚举器已经重置到起点并导致断言失败。

我无法理解发生了什么。我真的觉得自己是这个谜题的初学者。

我在这里想念什么?

4

2 回答 2

5

我想象它与 List.Enumerator 是一个结构有关。您将它传递给一个方法,对其进行操作,然后返回。对于您的原始实例,操作可能不会发生。

于 2012-03-10T02:02:30.113 回答
3

List<T>.Enumerator是一种值类型,意味着它被复制到方法的本地范围内,进行更改,然后在离开方法时销毁。也尝试通过引用传递它。

于 2012-03-10T02:03:46.090 回答