以下两种方法(一种使用IEnumerator<int>,另一种使用List<int>.Enumerator),即使看起来相同,也会产生不同的结果。
static void M1()
{
var list = new List<int>() { 1, 2, 3, 4 };
IEnumerator<int> iterator = list.GetEnumerator();
while (iterator.MoveNext())
{
Console.Write(iterator.Current);
}
iterator.Reset();
while (iterator.MoveNext())
{
Console.Write(iterator.Current);
}
}
static void M2()
{
var list = new List<int>() { 1, 2, 3, 4 };
//Here the iterator will be List<int>.Enumerator (which is a struct)
var iterator = list.GetEnumerator();
while (iterator.MoveNext())
{
Console.Write(iterator.Current);
}
//This will not work, as Reset method was implemented explicitly
//iterator.Reset();
//So casting it to IEnumerator is required
//which will lead to boxing and other issues of struct and interface
((IEnumerator<int>)iterator).Reset();
//Following loop will NOT work
while (iterator.MoveNext())
{
Console.Write(iterator.Current);
}
}有几个问题可以清楚地解释这种行为,您可以检查它们-- 这里、这里和这里。
我仍然有两个疑问
发布于 2014-04-18 11:05:42
为什么List.Enumerator不抛出"NotSupportedException“来重置?
因为微软没有时间机器来预测5年后会发生什么。类型推断背后的强大动力是Linq,它并不是在上世纪90年代末仿制药第一次开发时的路线图上。拳击问题不是一个没有它的问题。
为什么重置是显式实现的,而不是像MoveNext和Current那样隐式实现的?
因为不能取消继承接口方法,所以只能隐藏它。IEnumerator有一个重置()方法是另一个时间机器问题,这是在1995年COM自动化设计时决定的。在选择和结果之间还有大约5年的差距:) .NET必须在COM迭代器和.NET迭代器之间提供一个很好的映射,这样才有被采用的战斗机会。
从链接中可以看出,COM迭代器的另一个功能是克隆。这是ICloneable接口背后的动力,这是.NET中另一个非常麻烦的接口,在他们的泛型兄弟中实现起来太麻烦了,只有非泛型集合枚举器才能实现它。
微软的工作很艰难,每个设计决策都是他们必须永远接受的。我们的操作要简单得多,我们可以简单地不使用Reset :)
发布于 2014-04-18 09:14:03
为什么List.Enumerator不抛出"NotSupportedException“来重置?
为什么要这样做呢?List<T>是一种实现Reset非常简单的类型,那么为什么不实现它呢?
为什么重置是显式实现的,而不是像MoveNext和Current那样隐式实现的?
我认为这是因为现在普遍认为Reset是一个错误。但它确实存在,因此必须以某种方式加以实施。因此,使用显式接口实现隐藏它是有意义的,它说“您可能不应该使用这个”。
https://stackoverflow.com/questions/23150668
复制相似问题