有人能给我解释一下IEnumerable和IEnumerator吗?
例如,什么时候用它胜过foreach?IEnumerable和IEnumerator的区别是什么?为什么我们需要使用它?
有人能给我解释一下IEnumerable和IEnumerator吗?
例如,什么时候用它胜过foreach?IEnumerable和IEnumerator的区别是什么?为什么我们需要使用它?
当前回答
IEnumerable实现了GetEnumerator。当调用时,该方法将返回一个IEnumerator,它实现了MoveNext, Reset和Current。
因此,当你的类实现IEnumerable时,你是在说你可以调用一个方法(GetEnumerator)并返回一个新的对象(一个IEnumerator),你可以在循环中使用,比如foreach。
其他回答
实现IEnumerable意味着你的类返回一个IEnumerator对象:
public class People : IEnumerable
{
IEnumerator IEnumerable.GetEnumerator()
{
// return a PeopleEnumerator
}
}
实现IEnumerator意味着你的类返回迭代的方法和属性:
public class PeopleEnumerator : IEnumerator
{
public void Reset()...
public bool MoveNext()...
public object Current...
}
这就是区别所在。
通过类比+代码演练进行解释
类比:假设你是一架飞机上的侦探。你得在所有乘客中找到嫌疑人。
一架飞机只能这样做,如果它是:
可数名词, 如果它有计数器。
可数是什么意思?
如果一家航空公司是可数的,这意味着飞机上必须有一名空乘人员,他的唯一工作就是数数:
柜台/空乘人员必须先于第一位乘客开始工作。(即空乘人员)必须“下一个移动”到过道的第一个座位。 然后他/她要记录:(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)了解他正在处理的当前对象。
可枚举的只是“可数的”的一个花哨的词。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Enudemo
{
class Person
{
string name = "";
int roll;
public Person(string name, int roll)
{
this.name = name;
this.roll = roll;
}
public override string ToString()
{
return string.Format("Name : " + name + "\t Roll : " + roll);
}
}
class Demo : IEnumerable
{
ArrayList list1 = new ArrayList();
public Demo()
{
list1.Add(new Person("Shahriar", 332));
list1.Add(new Person("Sujon", 333));
list1.Add(new Person("Sumona", 334));
list1.Add(new Person("Shakil", 335));
list1.Add(new Person("Shruti", 336));
}
IEnumerator IEnumerable.GetEnumerator()
{
return list1.GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
Demo d = new Demo(); // Notice here. it is simple object but for
//IEnumerator you can get the collection data
foreach (Person X in d)
{
Console.WriteLine(X);
}
Console.ReadKey();
}
}
}
/*
Output :
Name : Shahriar Roll : 332
Name : Sujon Roll : 333
Name : Sumona Roll : 334
Name : Shakil Roll : 335
Name : Shruti Roll : 336
*/
实现IEnumerable可以让你获得一个列表的IEnumerator。
IEnumerator允许使用yield关键字以foreach样式顺序访问列表中的项。
在foreach实现之前(例如在Java 1.4中),迭代列表的方法是从列表中获取一个枚举器,然后向它请求列表中的“下一个”项,只要作为下一个项返回的值不为空。Foreach只是隐式地将其作为一种语言特性来实现,与lock()在幕后实现Monitor类的方式相同。
我期望foreach工作在列表上,因为它们实现了IEnumerable。
例如,什么时候用它胜过foreach?
你不用IEnumerable "over" foreach。实现IEnumerable使得使用foreach成为可能。
当你写这样的代码时:
foreach (Foo bar in baz)
{
...
}
它在功能上相当于这样写:
IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
bar = (Foo)bat.Current
...
}
所谓“功能等效”,我指的是编译器实际将代码转换成的内容。在本例中,除非baz实现了IEnumerable,否则不能在baz上使用foreach。
IEnumerable表示baz实现了该方法
IEnumerator GetEnumerator()
该方法返回的IEnumerator对象必须实现这些方法
bool MoveNext()
and
Object Current()
第一个方法前进到创建枚举器的IEnumerable对象中的下一个对象,如果完成则返回false,第二个方法返回当前对象。
. net中任何你可以迭代的东西都实现了IEnumerable。如果您正在构建自己的类,并且它还没有从实现了IEnumerable的类继承,那么您可以通过实现IEnumerable(并通过创建其新的GetEnumerator方法将返回的枚举器类)使您的类在foreach语句中可用。