[英]Why is IEnumerable<T> necessary when there is IEnumerator<T>?
[英]Why doesn't the following work? (IEnumerable/ IEnumerator)
我在这个MSDN页面上尝试了这个例子。 我试图更改GetEnumerator
方法。 我知道有些东西似乎不对,但它符合,然后不运行。 错误是Enumerator尚未启动并且应该MoveNext
,但它正在被调用!
class Program
{
static void Main(string[] args)
{
foreach (var day in new DaysOfTheWekk())
{
Console.WriteLine(day) ;
}
Console.ReadLine();
}
}
public class DaysOfTheWekk: IEnumerable
{
private string[] days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
public IEnumerator GetEnumerator()
{
days.GetEnumerator().MoveNext();
yield return days.GetEnumerator().Current;
}
}
你为什么要打电话给moveNext? 请忽略.Current
:
public class DaysOfTheWeek: IEnumerable
{
private string[] days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
public IEnumerator GetEnumerator()
{
return days.GetEnumerator();
}
}
否则使用while
循环,因为:
public class DaysOfTheWeek: IEnumerable
{
private string[] days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
public IEnumerator GetEnumerator()
{
var enumerator = days.GetEnumerator();
while(enumerator.MoveNext())
{
yield return enumerator.Current;
}
}
}
说明: GetEnumerator()
方法总是返回一个新的枚举器,因此如果调用GetEnumerator().Current
,则不会在新返回的实例上MoveNext()
函数! 请使用我的第二个示例中所述的变量。
您已在另一个枚举器上调用了MoveNext()
你的代码相当于
public IEnumerator GetEnumerator()
{
var enumerator1 = days.GetEnumerator();
enumerator1.MoveNext();
var enumerator2 = days.GetEnumerator();
yield return enumerator2.Current;
}
每次调用GetEnumerator()
,都会构造一个新的枚举器(至少对于IEnumerable
BCL实现),正如您从上面的代码中看到的那样,您构造了两个枚举器并在一个上调用MoveNext而在另一个上调用Current。 这是属性和方法之间的关键概念差异。 应该期望一个方法返回一个操作的结果,而一个属性应该返回相同的值,除非该对象的状态发生了变化。 您的代码中似乎也存在逻辑错误,您只返回第一个元素,如果没有则会失败,所以基本上您已经实现了.Single()
方法,如果您更改为
public IEnumerator GetEnumerator()
{
var enumerator = days.GetEnumerator();
while(enumerator.MoveNext()){
yield return enumerator.Current;
}
}
这当然与功能相同
public IEnumerator GetEnumerator()
{
foreach(var day in days){
yield return day;
}
}
days.GetEnumerator().MoveNext();
yield return days.GetEnumerator().Current;
在这里,您可以创建两个不同的枚举器。 您在第一个上调用MoveNext
,然后在下面的行中创建另一个并在其上访问Current
。
另一种解决方案是,在调用方法GetEnumerator()时,应确保始终返回相同的迭代器。 这是示例实现:
public class DaysOfTheWeek : IEnumerable
{
private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
private IEnumerator iterator;
public DaysOfTheWeek()
{
iterator = days.GetEnumerator();
iterator.MoveNext();
}
public IEnumerator GetEnumerator()
{
return iterator;
}
}
不需要在构造函数中调用MoveNext(),您必须在iterator.current之前调用iterator.MoveNext()方法。
关键是当您调用GetEnumerator()方法时,您将始终使用相同的迭代器。
我想你假设days.GetEnumerator()
总是返回相同的枚举器。 它有一个很好的理由每次返回一个新的 - 如果只有一个,不同的代码片段无法同时枚举。 它组成不好。
调用days.GetEnumerator()
一次,或写入return days.GetEnumerator();
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.