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 への 2 回目の呼び出しでは、列挙子が既に開始点にリセットされ、アサーションが失敗したようです。

何が起こるか理解できません。私はこのパズルの初心者のように感じます。

ここで何が恋しいですか?

4

2 に答える 2

5

List.Enumerator が構造体であることと関係があると想像しています。それをメソッドに渡し、操作してから返します。おそらく、元のインスタンスでは操作は行われていないでしょう。

于 2012-03-10T02:02:30.113 に答える
3

List<T>.Enumeratorメソッドのローカル スコープにコピーされ、変更され、メソッドを終了するときに破棄されることを意味する値型です。参照渡しも試してみてください。

于 2012-03-10T02:03:46.090 に答える