我在这个MSDN page上尝试了这个例子。我试图更改GetEnumerator
方法。我知道有些东西在这方面看起来不对,但它符合并且不会运行。错误是枚举器尚未启动且应该调用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;
}
}
答案 0 :(得分:3)
为什么要调用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()
函数!请使用我的第二个示例中所述的变量。
答案 1 :(得分:3)
您已在其他枚举器上调用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;
}
}
答案 2 :(得分:1)
days.GetEnumerator().MoveNext();
yield return days.GetEnumerator().Current;
在这里,您可以创建两个不同的枚举器。您先在 上调用MoveNext
,然后在下面的行中创建另一个,然后访问Current
。
答案 3 :(得分:1)
另一种解决方案是,在调用方法GetEnumerator()时,应确保始终返回相同的Iterator。这是示例实现:
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()方法时,你将始终使用相同的迭代器。
答案 4 :(得分:0)
我认为你假设days.GetEnumerator()
总是返回相同的枚举器。它有一个很好的理由每次返回一个新的 - 如果只有一个,不同的代码片段无法同时枚举。这不会很好。
拨打days.GetEnumerator()
一次,或写下return days.GetEnumerator();
。