什么时候应该使用IEnumerable和GetEnumerator?

时间:2012-03-23 10:59:02

标签: c# .net

在我们的许多项目中,我看到了一些自定义集合或容器类,它们包含某种通用集合,例如:一个List(of T)课程。

它们通常有一个GetXXX方法,它返回自定义集合类使用的任何类型的IEnumerable,因此可以使用foreach循环迭代内部集合。

e.g。

public IEnumerable<UploadState> GetStates
{
    get
    {
        return new List<UploadState>(m_states);
    }
}

我的问题是,这些类应该实现IEnumerable接口,并在List本身上调用GetEnumerator

是否有首选方式,还是由开发人员负责?

6 个答案:

答案 0 :(得分:2)

我会这样做:

public IEnumerable<UploadState> GetStates
{
    get
    {
        foreach (var state in m_states) { 
            yield return state; 
        }
    }
}

它更干净,您的用户没有得到他们不应该的列表(毕竟他们可以将它转换为List<T>)并且您不需要创建List<T>对象

编辑:误解了这个问题。我认为如果该类是一个集合,它应该实现IEnumerable<T>

答案 1 :(得分:2)

如果您的类是自定义集合类,则是,它应该实现IEnumerable<T>。在这种情况下,内部列表的公共属性将是多余的。想象一个简单的课程:

public class People : IEnumerable<Person>
{
    List<Person> persons = new List<Person>();

    public IEnumerator<Person> GetEnumerator()
    {
        return persons.GetEnumerator();
    }
}

但是,如果您的类不能像集合那样行事,那么为其元素提供公共IEnumerable属性:

public class Flight
{
    List<Person> passengers = new List<Person>();

    public IEnumerable<Person> Passengers
    {
        get { return passengers; }
    }
}

无论如何,开发人员总是应该选择合适的设计。

答案 2 :(得分:1)

请在代码示例中考虑创建列表。我不知道m_states是什么,但如果这是一个值类型集合,则创建原始列表的克隆。通过这种方式,可以从调用者添加/删除/更新元素操纵返回列表。 没有影响原始数据。

如果m_states是引用类型,则仍然会创建一个列表,调用者可以再次操作添加/删除/ 更新元素(它是参考!)而不影响原始数据。

IEnumerable<T>怎么样,它只是一种使返回类型通用的方法,而不是与List<T>类型强耦合。

答案 3 :(得分:0)

您应该根据System.Collections.ObjectModel命名空间中的一个类派生自定义集合类。它们已经包含IEnumerable<T>和非通用IEnumerable接口的实现。

答案 4 :(得分:0)

我认为如果您新实现的类的行为与列表的行为相同,则无需实现它。如果你需要某种自定义逻辑,那取决于你想做什么;你可以继承列表,也可以实现IEnumerable。这取决于要实现的目标。

答案 5 :(得分:0)

您可能想要检查一下: http://www.codeproject.com/Articles/4074/Using-IEnumerator-and-IEnumerable-in-the-NET-Frame

我还没有完整阅读,但我认为这可以回答你的问题。