列表的重置方法的行为.枚举 数
本文关键字:枚举 方法 列表 | 更新日期: 2023-09-27 17:58:49
以下两种方法(一种使用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);
}
}
有几个问题可以清楚地解释这种行为,你可以在这里、这里和这里检查它们。
我还有以下两个疑问
- 为什么 List.Enumerator 不会抛出"NotSupportedException"进行重置?
- 为什么 Reset 是显式实现的,而不是像 MoveNext 和 Current 那样隐式实现的?
为什么 List.Enumerator 不会抛出"NotSupportedException"进行重置?
因为Microsoft没有时间机器来预测5年后会发生什么。 类型推断背后的强大推动力是 Linq,只是在 1990 年代后期首次开发泛型时,它还没有出现在路线图上。 没有它,拳击问题就不是问题。
为什么 Reset 是显式实现的,而不是像 MoveNext 和 Current 那样隐式实现的?
由于无法取消继承接口方法,因此只能隐藏它。 IEnumerator 有一个 Reset(( 方法是另一个时间机器问题,这是在 1995 年设计 COM Automation 时决定的。 选择和后果之间大约还有5年的差距:) .NET 必须在 COM 迭代器和 .NET 迭代器之间提供一个体面的映射,以便有机会被采用。
从链接中可以看出,COM 迭代器中的另一项功能是克隆。 这是 ICloneable 接口背后的动力,这是 .NET 中另一个非常麻烦的接口。 那个在他们的泛型兄弟中实现起来太麻烦了,只有非泛型集合枚举器才能实现它。
Microsoft的工作很艰难,每一个设计决策都是他们必须永远忍受的。 我们的要容易得多,我们根本无法使用重置:)
为什么 List.Enumerator 不会抛出"NotSupportedException"进行重置?
为什么呢? List<T>
是一种实现Reset
是微不足道的类型,那么为什么不实现它呢?
为什么 Reset 是显式实现的,而不是像 MoveNext 和 Current 那样隐式实现的?
我认为这是因为Reset
现在通常被认为是一个错误。但它确实存在,所以必须以某种方式实现。因此,使用显式接口实现隐藏它是有意义的,它说"你可能不应该使用它"。