发表于: 2013-11-08 01:41:55
http://bbs.csdn.net/topics/390636800本帖最后由 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 请按任意键继续. . . |
|
#1 得分:0
回复于: 2013-11-08 02:33:09
代码一改成这样也行,这到底是怎么回事?
public IEnumerator GetEnumerator() { return this.names.GetEnumerator(); //for (int i = 0; i < names.Length; i++) //{ // yield return names[i];//返回迭代器 //} } |
#2 得分:0
回复于: 2013-11-08 02:51:52
是这样的,如果要对一个对象使用foreach,那么它必须包含一个GetEnumerator()方法,无参数,返回类型任意,同时返回的类型必须包含Current属性和MoveNext方法。编译器会自动去绑定,因此不需要IEnumerable和IEnumerator。其实接口的本质就是让编译器去绑定一个对象的方法,在这里,C#编译器的确不依赖接口。
下面的代码不使用IEnumerable和IEnumerator:
至于yield,则是C#编译器自动为你产生两个类,一个包含GetEnumerator,一个包含Current和MoveNext | |||
|
#3 得分:0
回复于: 2013-11-08 03:06:02
本帖最后由 caozhy 于 2013-11-08 03:14:54 编辑
这段代码展示了让foreach工作的最简代码 上面我们分出A B是因为告诉你,A B可以是不同的类。 当然我们也可以在一个类中实现:
下面是使用yield的等价版本:
A相当于:ConsoleApplication1. Program+<foo>d__0 //这是C#编译器为你生成的类,兼具了上面代码 A B 的作用。 B相当于:ConsoleApplication1.Program+<foo>d__0 ConsoleApplication1.Program+<foo>d__0的方法: System.Collections.Generic.IEnumerable<System.String>. GetEnumerator System.Collections.IEnumerable.GetEnumerator MoveNext System.Collections.Generic.IEnumerator<System.String>. get_Current System.Collections.IEnumerator.Reset System.IDisposable.Dispose System.Collections.IEnumerator. get_Current ToString Equals GetHashCode GetType Finalize MemberwiseClone Hello World ... Hello World Press any key to continue . . . 当你用foreach (object s in foo())的时候,调用非泛型的Current版本,否则调用泛型的版本。 |