关于IEnumerable与IEnumerator还是不懂
本帖最后由 jxfinest 于 2013-11-08 02:37:59 编辑 using System;
using System.Collections;
namespace ConsoleApplication11
{
class Program
{
public class D9TecMembers:IEnumerable //把:IEnumerable去掉貌似也可以(去不去掉无所谓,因为代码已经实现了相应的接口)。再把代码一中的GetEnumerator换任意名,就不行,而再把IEnumerator改成IEnumerable就行了,感觉IEnumerable条件更宽松,可以这样说吧?后边跟什么名称的方法都可以,但IEnumerator就不行了,跟其它的方法名就不行(会出现“System.Collections.IEnumerator”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“System.Collections.IEnumerator”类型的变量),必须与GetEnumerator()相互结合(如果有public IEnumerator GetEnumerator()这行语句的话,但是去掉也不会出错),所以由此得出结论,这里的GetEnumerator()并不是普通的方法名,它与IEnumerator相配的话下边对应的代码二为foreach (string title in titles),它与IEnumerable相配的时候是任意名的性质,下边的对应的代码二为foreach (string title in titles. GetEnumerator())。有哪位高手能为我解释一下这种现象的理由吗?
{
string[] names = { "Wei Gao", "Zhao Zhang", "Changji Song", "Zhike Chang", "Denian Zhang", "Zhaotian Yang", "Guangyue Cai" };
public IEnumerator GetEnumerator()//代码一
{
for (int i = 0; i < names.Length; i++)
{
yield return names[i];//返回迭代器
}
}
public IEnumerable Reverse()
{
for (int i = names.Length - 1; i >= 0; i--)
{
yield return names[i];
}
}
public IEnumerable Subset(int index, int length)
{
for (int i = index; i < index + length; i++)
{
yield return names[i];
}
}
}
static void Main(string[] args)
{
D9TecMembers titles = new D9TecMembers();
foreach (string title in titles)//代码二
{
Console.WriteLine(title);
}
Console.WriteLine();
foreach (string title in titles.Reverse())
{
Console.WriteLine(title);
}
Console.WriteLine();
foreach (string title in titles.Subset(1, 2))
{
Console.WriteLine(title);
}
Console.ReadKey();
}
}
}
输出
Wei Gao
Zhao Zhang
Changji Song
Zhike Chang
Denian Zhang
Zhaotian Yang
Guangyue Cai
Guangyue Cai
Zhaotian Yang
Denian Zhang
Zhike Chang
Changji Song
Zhao Zhang
Wei Gao
Zhao Zhang
Changji Song
请按任意键继续. . .
迭代器 IEnumerable IEnumerator
[解决办法]
是这样的,如果要对一个对象使用foreach,那么它必须包含一个GetEnumerator()方法,无参数,返回类型任意,同时返回的类型必须包含Current属性和MoveNext方法。编译器会自动去绑定,因此不需要IEnumerable和IEnumerator。其实接口的本质就是让编译器去绑定一个对象的方法,在这里,C#编译器的确不依赖接口。
下面的代码不使用IEnumerable和IEnumerator:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class D9TecMembers
{
public class DefaultEnumerator
{
private string[] value;
private int n = 0;
public DefaultEnumerator(string[] value) { this.value = value; }
public object Current
{
get { return value[n]; }
}
public bool MoveNext()
{
return ++n < value.Length;
}
}
string[] names = { "Wei Gao", "Zhao Zhang", "Changji Song", "Zhike Chang", "Denian Zhang", "Zhaotian Yang", "Guangyue Cai" };
public DefaultEnumerator GetEnumerator()
{
return new DefaultEnumerator(names);
}
}
static void Main(string[] args)
{
D9TecMembers titles = new D9TecMembers();
foreach (string title in titles)
{
Console.WriteLine(title);
}
}
}
}
至于yield,则是C#编译器自动为你产生两个类,一个包含GetEnumerator,一个包含Current和MoveNext