黑马程序员技术交流社区

标题: foreach对象必须实现什么接口或方法? [打印本页]

作者: 李行周    时间: 2012-11-18 23:16
标题: foreach对象必须实现什么接口或方法?
本帖最后由 李行周 于 2012-11-27 00:24 编辑

foreach对象必须实现什么接口或方法?
作者: 吴瑞祥    时间: 2012-11-19 06:35
foreach是迭代循环语句吧
作者: 马毅    时间: 2012-11-19 08:55
IEnumerable接口,GetEnumerator方法
作者: 崔晓聪    时间: 2012-11-19 09:00
在使用foreach集合进行遍历的时候,要求被遍历的对象必须实现了 IEnumerable 接口,而该接口的唯一成员方法GetEnumerator返回实现了Ienumator接口的实例对象。
作者: 陈辉    时间: 2012-11-19 09:03
本帖最后由 陈辉 于 2012-11-19 09:10 编辑

1、源代码
static void Main(string[] args)
        {
            List<string> list = new List<string> { "Lucy", "Jim", "Tom" };

        //-----------------------foreach实现的---------------------------------------
            //foreach (string s1 in list)
            //{
            //    Console.WriteLine(s1);
            //}

        //-----------------------foreach的内部实现机制--------------------------------
            IEnumerator<string> enumerator = list.GetEnumerator();
            while (enumerator.MoveNext())
            {
                string s1 = enumerator.Current;
                Console.WriteLine(s1);
            }
            Console.ReadKey();
        }

2、对foreach的内部实现机制的代码的解释:
     a、List泛型类的GetEnumerator方法是在IEnumerable<T>接口定义的,因此List泛型类要实现IEnumerable<T>接口
     b、 List泛型类的GetEnumerator方法 返回的是List<T>.Enumerator,而List<T>.Enumerator是在List泛型类 内部定义的一个结构,它实现了IEnumerator<T>接口,因此,要想用foreach,那么自定      
          义的类必须实现 IEnumerable或IEnumerable<T> 和IEnumerator 或 IEnumerator<T>     
     c、再调用 IEnumerator<T>接口 中的MoveNext方法,当调用一次MoveNext方法时,就遍历集合中的一个元素,并将当前遍历的元素保存到IEnumerator<T>接口 的Current属性中
          MoveNext方法的内部实现(可以用.net reflector查看List泛型类 实现的MoveNext方法)
public bool MoveNext()
{
    List<T> list = this.list; //获得List泛型集合
    if ((this.version == list._version) && (this.index < list._size))
    {
       //   list._items[this.index]   ->获得当前遍历的元素
       //并单签遍历的元素保存到IEnumerator<T>接口 的Current属性中
        this.current = list._items[this.index];
        this.index++;//index加1,以便下次调用MoveNext方法时,获取下一个元素
        return true;
    }
    return this.MoveNextRare();
}
3、当在foreach中用其他集合时,foreach的内部实现机制和List泛型集合的实现大同小异。









作者: 王新阳    时间: 2012-11-19 10:01
能用foreach遍历访问的对象必须是集合或数组对象,而这些都是靠实现超级接口IEnumerator或被声明 GetEnumerator 方法的类型
作者: 静等花开    时间: 2012-11-19 10:20
平常使用foreach in 的时候都是用的系统定义好的集合类(实现ICollection接口)。比如 arrayList,stringDictionary ,数组等。这些是平台封装好的,已近实现了IEnumerator 接口了。要让自己写的类也能时候foreach 就必须 在编写类的时候实现该接口。这样就可以事后foreach遍历了。比如 定义一个 people 的类,实现了IEnumerator接口。有一个数组 People[] tempPeople ,那么 就可以用: foreach( p in tempPeople){  console.writeline(p.name);}这样就免去了用for 循环的麻烦。至于怎么样去实现Iemumerator接口。查一下MSDN 就可以啦。
作者: 王彬    时间: 2012-11-19 12:43
能用foreach遍历访问的对象必须是集合或数组对象,而这些都是靠实现超级接口IEnumerator或被声明 GetEnumerator 方法的类型
作者: 韩俊    时间: 2012-11-19 13:22
       
IEnumerable接口,GetEnumerator方法

作者: 刘俊红    时间: 2012-11-26 23:42
本帖最后由 刘俊红 于 2012-11-26 23:45 编辑

楼主这个问题《C#图解教程2010    20.枚举数和迭代器》讲的极其详细和清楚。
我的总结如下:
一个类的数据成员能被foreach迭代的本质是什么?[_并且没有共享混乱出现]
本质:该类具有一个签名为publict ReturnedType GetEnumerator()的方法,ReturnType类型满足条件:一个公共的MoveNext()方法,一个公共的Current属性。
所以
1)类并不需要必须实现IEnumerable <T>或者IEnumerable接口,只需要一个满足上面签名的方法。
2)这个方法的返回值不需要必须实现IEnumerator <T>或者IEnumertor接口,只需要有一个公共MoveNext()方法和一个公共Current属性
【当然,你必须在这两个里面实现正确的逻辑】

一个类的数据成员能被foreach迭代的本质是它有一个能返回枚举数的GetEnumerator()方法。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2