有人能给我解释一下IEnumerable和IEnumerator吗?
例如,什么时候用它胜过foreach?IEnumerable和IEnumerator的区别是什么?为什么我们需要使用它?
有人能给我解释一下IEnumerable和IEnumerator吗?
例如,什么时候用它胜过foreach?IEnumerable和IEnumerator的区别是什么?为什么我们需要使用它?
当前回答
我注意到了这些不同之处:
A.我们以不同的方式迭代列表,foreach可用于IEnumerable, while loop可用于IEnumerator。
B.当我们从一个方法传递到另一个方法时,IEnumerator可以记住当前索引(它开始使用当前索引),但IEnumerable不能记住索引,它将索引重置为开始。更多内容请参见https://www.youtube.com/watch?v=jd3yUjGc9M0
其他回答
实现IEnumerable可以让你获得一个列表的IEnumerator。
IEnumerator允许使用yield关键字以foreach样式顺序访问列表中的项。
在foreach实现之前(例如在Java 1.4中),迭代列表的方法是从列表中获取一个枚举器,然后向它请求列表中的“下一个”项,只要作为下一个项返回的值不为空。Foreach只是隐式地将其作为一种语言特性来实现,与lock()在幕后实现Monitor类的方式相同。
我期望foreach工作在列表上,因为它们实现了IEnumerable。
实现IEnumerable本质上意味着可以遍历对象。这并不一定意味着它是一个数组,因为有一些列表不能被索引,但你可以枚举它们。
IEnumerator是用于执行迭代的实际对象。它控制从一个对象移动到列表中的下一个对象。
大多数情况下,IEnumerable和IEnumerator被透明地用作foreach循环的一部分。
IEnumerable和IEnumerator的区别:
IEnumerable内部使用IEnumerator。 IEnumerable不知道哪个项目/对象正在执行。 无论何时将IEnumerator传递给另一个函数,它都知道项/对象的当前位置。 当我们将IEnumerable集合传递给另一个函数时,它 不知道项目/对象的当前位置(不知道正在执行哪个项目) IEnumerable有一个方法GetEnumerator()
public interface IEnumerable<out T>: IEnumerable { IEnumerator < T > GetEnumerator (); }
IEnumerator有一个名为Current的属性和两个方法,Reset()和MoveNext()(这对于了解列表中项目的当前位置非常有用)。
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
通过类比+代码演练进行解释
类比:假设你是一架飞机上的侦探。你得在所有乘客中找到嫌疑人。
一架飞机只能这样做,如果它是:
可数名词, 如果它有计数器。
可数是什么意思?
如果一家航空公司是可数的,这意味着飞机上必须有一名空乘人员,他的唯一工作就是数数:
柜台/空乘人员必须先于第一位乘客开始工作。(即空乘人员)必须“下一个移动”到过道的第一个座位。 然后他/她要记录:(i)坐在座位上的人,以及(ii)他们目前在过道上的位置。
计数器一直往前走,直到他到达飞机的尽头。
让我们把它和IEnumerables联系起来
foreach (Passenger passenger in Plane)
// the airline hostess is now at the front of the plane
// and slowly making her way towards the back
// when she get to a particular passenger she gets some information
// about the passenger and then immediately heads to the cabin
// to let the captain decide what to do with it
{ // <---------- Note the curly bracket that is here.
// we are now cockpit of the plane with the captain.
// the captain wants to give the passenger free
// champaign if they support manchester city
if (passenger.supports_mancestercity())
{
passenger.getFreeChampaign();
}
else
{
// you get nothing! GOOD DAY SIR!
}
} // <---- Note the curly bracket that is here!
// the hostess has delivered the information
// to the captain and goes to the next person
// on the plane (if she has not reached the
// end of the plane)
总结
换句话说,有计数器的东西是可数的。计数器必须(基本上):(i)记住它的位置(状态),(ii)能够下一步移动,(iii)了解他正在处理的当前对象。
可枚举的只是“可数的”的一个花哨的词。
理解Iterator模式将对您有所帮助。我建议你也读一下。
迭代器模式
在高层次上,迭代器模式可用于提供一种遍历任何类型集合的标准方法。 迭代器模式中有3个参与者,实际的集合(客户端)、聚合器和迭代器。聚合是一个接口/抽象类,具有返回迭代器的方法。Iterator是一个接口/抽象类,它具有允许我们遍历集合的方法。
为了实现该模式,我们首先需要实现一个迭代器来生成一个具体的迭代器,该迭代器可以遍历相关的集合(客户端) 然后集合(客户端)实现聚合器以返回上述迭代器的实例。
下面是UML图
在c#中,IEnumerable是抽象的集合IEnumerator是抽象的迭代器。IEnumerable有一个单独的方法GetEnumerator,它负责创建所需类型的IEnumerator实例。像list这样的集合实现了IEnumerable。
的例子。 假设我们有一个getPermutations(inputString)方法,它返回一个字符串的所有排列,并且该方法返回IEnumerable<string>的实例
为了计算排列的数量,我们可以像下面这样做。
int count = 0;
var permutations = perm.getPermutations(inputString);
foreach (string permutation in permutations)
{
count++;
}
c#编译器或多或少地将上面的转换为
using (var permutationIterator = perm.getPermutations(input).GetEnumerator())
{
while (permutationIterator.MoveNext())
{
count++;
}
}
如果你有任何问题,请尽管问。