何时应该使用IEnumerable和GetEnumerator
本文关键字:GetEnumerator IEnumerable 何时应 | 更新日期: 2023-09-27 18:28:59
在我们的许多项目中,我看到了一些自定义集合/或容器类,它们包含某种泛型集合,例如List(of T)
类。
它们通常有一个GetXXX方法,该方法返回自定义集合类使用的任何类型的IEnumerable,因此可以使用foreach循环对内部集合进行迭代。
例如
public IEnumerable<UploadState> GetStates
{
get
{
return new List<UploadState>(m_states);
}
}
我的问题是,这些类是否应该实现IEnumerable
接口,并在List本身上调用GetEnumerator
。
有没有首选的方式,或者由开发人员决定?
如果您的类是一个自定义集合类,那么是的,它应该实现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; }
}
}
不管怎样,总是由开发人员来选择正确的设计。
我会这样做:
public IEnumerable<UploadState> GetStates
{
get
{
foreach (var state in m_states) {
yield return state;
}
}
}
它更干净,用户不会在不应该得到的地方得到列表(毕竟他们可以将其转换为List<T>
),并且您不需要创建List<T>
对象。
编辑:误解了这个问题。我认为如果这个类是一个集合,那么它应该实现IEnumerable<T>
。
请考虑在您的代码示例中创建了一个新的列表。我不知道什么是m_states
,但如果这是一个值类型集合,则可以创建原始列表的克隆。通过这种方式,可以从调用方Add/Remove/Update元素中操作返回列表而不影响原始数据。
如果m_states
是引用类型,这仍然会创建一个新列表,该列表可以由调用方Add/Remove/No更新元素(它是引用!)再次操作,而不会影响原始数据。
IEnumerable<T>
呢,它只是使返回类型成为泛型的一种方式,而不是与List<T>
类型强耦合。
我认为,如果你新实现的类的行为与列表相同,那么就没有必要实现它。如果你需要某种自定义逻辑,这取决于你想做什么;您可以继承列表,也可以实现IEnumerable。这只是取决于要实现的目标。
您可能需要检查以下内容:http://www.codeproject.com/Articles/4074/Using-IEnumerator-and-IEnumerable-in-the-NET-Frame
我还没有完全阅读,但我认为这回答了你的问题。
您应该基于System.Collections.ObjectModel
命名空间中的一个类来派生自定义集合类。它们已经包含IEnumerable<T>
和非通用IEnumerable
接口的实现。