【发布时间】:2014-06-10 13:41:34
【问题描述】:
在集合的框架类中,我经常看到IEnumerator<T>单独实现为一个内部类,并在GetEnumerator方法中返回它的一个实例。
现在假设我正在编写自己的集合类,它将有一个像 List<T> 或 T[] 这样的内置集合在内部充当持有者,这样说:
public class SpecialCollection<T> : IEnumerable<T>
{
List<T> list;
public SpecialCollection<T>()
{
}
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
//or
return list.Where(x => some logic).GetEnumerator();
//or directly rely on yield keyword
yield return x; //etc
}
}
我应该编写自己的枚举器类,还是可以返回List<T> 类的枚举器?在什么情况下我应该编写自己的枚举器类?
我也有一个相关的问题。如果它不是那么重要或没有太大区别,为什么 BCL 中的每个集合类都编写自己的 IEnumerator?
例如,List<T> 类有类似的东西
T[] items;
public IEnumerator<T> GetEnumerator()
{
return new List<T>.Enumerator(items);
}
【问题讨论】:
-
相对于什么?其中许多类是在迭代器出现之前编写的。
-
泛型是与 yield 关键字同时引入的,如果我没记错的话
-
@JeppeStigNielsen 我认为
// some logic的意思是可以向枚举器添加一些额外的逻辑。 -
@Maarten 假设我编写自己的类型
class MyColl : IEnumerable<int>。我可以在内部将我的值保存在一个数组中,所以有一个字段private int[] array;。现在,当我需要实现通用接口时,我不能只说return array.GetEnumerator();(编译时错误),因为数组的非通用性质(这里是int[])。我可以通过return array.Select(x => x).GetEnumerator();解决这个问题。但这很浪费。而是使用return ((IEnumerable<int>)array).GetEnumerator();或等效的return array.AsEnumerable().GetEnumerator();。明白我的意思了吗? -
@nawfal:如果您返回数组的
IEnumerator<T>,您将无法检测到调用之间的列表更改,这应该会触发异常。
标签: c# .net enumerator ienumerator design-guidelines