C#的IEnumerable,IEnumerator的复位功能不会被调用 [英] C# IEnumerable, IEnumerator Reset Function Not Get Called

查看:285
本文介绍了C#的IEnumerable,IEnumerator的复位功能不会被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我basicly试图让我的课能够使用的foreach 进行迭代。我读了这篇教程。 MSDN 。这似乎很简单。不过,我有一个问题,当我想重复第二次。我调试它;而事实证明,它不叫重置()功能。

I'm basicly trying to make my class able to iterate using foreach. I read this tutorial. MSDN. It seems very straight forward. However, I have a problem when I want to iterate second time. I debugged it; and it turned out that it doesn't call the Reset() function.

class A : IEnumerable, IEnumerator
{
    int[] data = { 0, 1, 2, 3, 4 };

    int position = -1;

    public object Current
    {
        get
        {
            return data[position];
        }
    }

    public bool MoveNext()
    {
        position++;
        return (position < data.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    public IEnumerator GetEnumerator()
    {
        return (IEnumerator)this;
    }
}

当我运行以下主要功能;它永远不会调用复位()功能。因此,一个循环后,我永远无法再重复我的课。

When I run the following main function; it never calls Reset() function. So, after one loop I never be able to iterate my class again.

static void Main(string[] args)
{
    A a = new A();

    foreach (var item in a)
    {
        Console.WriteLine(item);
    }

    Console.WriteLine("--- First foreach finished. ---");

    foreach (var item in a)
    {
        Console.WriteLine(item);
    }
}



输出:



Output:

0
1
2
3
4
--- First foreach finished. ---
Press any key to continue . . .

有什么想法?

推荐答案

每个时间的foreach 被调用时,它要求一个的新的的IEnumerator 。回到你的类的实例是一个坏主意 - 你应该做一个单独的类来实现的IEnumerator ,并返回它,而不是

Each time foreach is called, it asks for a new IEnumerator. Returning your class instance is a bad idea - you should make a separate class to implement the IEnumerator, and return it instead.

这通常是通过使用嵌套(私人)类,并返回它的一个实例完成。你可以通过A类实例的私有类(给它访问数据),并把位置字段在这类。这将允许多个枚举被simulatenously创建,并将随后的foreach调用正常工作。

This is often done by using a nested (private) class, and returning an instance of it. You can pass the class A instance to the private class (giving it access to data), and put the position field in that class. It would allow more than one enumerator to be created simulatenously, and will work properly with subsequent foreach calls.

例如,修改你的代码,你会做这样的事情

For example, to modify your code, you'd do something like:

using System;
using System.Collections;

class A : IEnumerable
{
    int[] data = { 0, 1, 2, 3, 4 };

    public IEnumerator GetEnumerator()
    {
        return new AEnumerator(this);
    }

    private class AEnumerator : IEnumerator
    {
        public AEnumerator(A inst)
        {
            this.instance = inst;
        }

        private A instance;
        private int position = -1;

        public object Current
        {
            get
            {
                return instance.data[position];
            }
        }

        public bool MoveNext()
        {
            position++;
            return (position < instance.data.Length);
        }

        public void Reset()
        {
            position = -1;
        }

    }
}

请注意,你也可以直接返回数组的枚举(虽然我是假设你想学习如何使清洁统计员):

Note that you can also just return the array's enumerator directly (though I was assuming you were trying to learn how to make clean enumerators):

class A : IEnumerable
{
    int[] data = { 0, 1, 2, 3, 4 };

    public IEnumerator GetEnumerator()
    {
        return data.GetEnumerator();
    }
}



最后,你可以使用的 的迭代器在一个简单得多的方式来实现这一点:

Finally, you can use iterators to implement this in a far simpler manner:

class A : IEnumerable
{
    int[] data = { 0, 1, 2, 3, 4 };

    public IEnumerator GetEnumerator()
    {
        for (int i=0;i<data.Length;++i)
           yield return data[i];
    }
}



话虽这么说,我会强烈建议实施的IEnumerable< INT> 除了IEnumerable的。泛型在使用方面使这远远更好。

That being said, I would strongly recommend implementing IEnumerable<int> in addition to IEnumerable. Generics make this far nicer in terms of usage.

这篇关于C#的IEnumerable,IEnumerator的复位功能不会被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆