除了(IEnumerable返回GetEnumerator(),对于“foreach”IEnumerble是必不可少的)
几乎以下两种方法允许我们迭代集合。什么是
一个人的优势是什么? (我不是在问IEnumerable之间的区别 和IEnumerator)。
static void Main()
{
IEnumerator<int> em = MyEnumerator<int>(new int[] { 1, 2, 3, 4 });
IEnumerator<int> e = Collection<int>
(new int[] { 1, 2, 3, 4 }).GetEnumerator();
while (em.MoveNext())
{
Console.WriteLine(em.Current);
}
while (e.MoveNext())
{
Console.WriteLine(e.Current);
}
Console.ReadKey(true);
}
接近1
public static IEnumerator<T> MyEnumerator<T>(T[] vals )
{
T[] some = vals;
foreach (var v in some)
{
yield return v;
}
}
接近2
public static IEnumerable<T> Collection<T>(T[] vals)
{
T[] some = vals;
foreach (var v in some)
{
yield return v;
}
}
答案 0 :(得分:1)
如果我错了,请纠正我,但唯一的区别是IEnumerable和IEnumerator之间的区别,因为你明确表示你不是要求区别,两者都是好的......
答案 1 :(得分:1)
主要区别在于,大多数API都支持IEnumerable<T>
但不支持IEnumerator<T>
。
您还必须记住在使用时调用Reset(),而IEnumerable<T>
中的语法更明显(只需再次调用GetEnumerator
)。另请参阅Eric Lipper关于重置是一个坏主意的评论;如果你的IEnumerator<T>
没有实现重置,或者它是一个一次性的枚举器(在很多情况下都没用)。
另一个区别可能是您可以同时从多个线程枚举IEnumerable<T>
,但IEnumerator<T>
在枚举数据中存储一个位置(想象一下RandomEnumerable
或RangeEnumerable
)。
所以结论是IEnumerable<T>
更通用,但无论如何,如果你有一个函数返回一个IEnumerator<T>
生成IEnumerable<T>
就很简单了。
class EnumeratorWrapper<T> : IEnumerable<T>
{
Func<IEnumerator<T>> m_generator;
public EnumeratorWrapper(Func<IEnumerator<T>> generator)
{
m_generator = generator;
}
public IEnumerator<T> GetEnumerator()
{
return m_generator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return m_generator();
}
}
使用IEnumerable<T>
只是为了API一致性似乎是我的最佳解决方案。
但Reset()
中的IEnumerator<T>
问题无论如何都会使其成为无法使用的解决方案,因此IEnumerable<T>
是可行的方法。