(C#新手)
有人可以解释,为什么命名迭代器(我在MS C编程指南中找到的术语)应该返回IEnumerable
// Implementing the enumerable pattern
public System.Collections.IEnumerable SampleIterator(int start, int end)
{
for (int i = start; i <= end; i++)
{
yield return i;
}
}
当类实现GetEnumerator()
或IEnumerable
接口的IEnumerable<T>
时,这是有道理的,但我不确定它为什么以及如何对方法和属性起作用。
编辑:有人指出我的问题不是很好。(也许,我仍然在思考C ++)
澄清:为了在某个类的对象上使用foreach
循环,类需要实现IEnumerable
和IEnumerator
接口或yield return
(即编译器处理所有内容)。
例如:
class ListClass : System.Collections.IEnumerable
{
public System.Collections.IEnumerator GetEnumerator() {...//uses yield return }
....
}
....
ListClass listClass1 = new ListClass(); // class implements IEnumerable interface method
foreach (int i in listClass1) {...}
在上面的示例中,GetEnumerator()
已实现,如果您希望对象在foreach
循环中运行,据我所知,必须实现GetEnumerator()
。
但是,当实现了命名迭代器(上面的代码)时,IEnumberable<T>
不是必需的,并且只有{{1}}(或非泛型)必须由方法/属性返回。
希望这能澄清我的问题。
答案 0 :(得分:4)
实际上,在这种情况下,我会说它应该返回IEnumerable<T>
- 或IEnumerable<int>
。但原因是因为它起作用,并且因为迭代器块(具有yield
语法的方法)可以为您实现该模式。如果您想执行与foreach
一起使用的 else ,则必须编写自己的CustomEnumerable
/ CustomIterator
,并手动实现状态机迭代器使用MoveNext()
/ Current
模式,记住在finally
中放置任何Dispose()
等。很多工作;收获不多。
编辑:这是一个编写得很糟糕的,可能是错误的实现方法,即手工返回自定义迭代器。请注意,返回int[]
或List<int>
非常简单,但会显着改变语义:它不再是假脱机迭代器,这是yield
创建的:
static CustomEnumerable SampleIteratorHard(int start, int end)
{
return new CustomEnumerable(start, end);
}
class CustomEnumerable
{
private readonly int start, end;
public CustomEnumerable(int start, int end)
{
this.start = start;
this.end = end;
}
public CustomIterator GetEnumerator()
{
return new CustomIterator(start, end);
}
}
class CustomIterator
{
private readonly int start, end;
int i, state, value;
public CustomIterator(int start, int end)
{
this.start = start;
this.end = end;
start = 0;
}
public bool MoveNext()
{
if (state == 2) return false;
if (state == 0)
{
i = start - 1; // to leave space for the ++
state = 1;
}
if (state == 1)
{
i++;
if (i <= end)
{
value = i;
return true;
}
}
state = 2;
return false;
}
public int Current { get { return value; } }
}