关于IEnumerable <t> </t>的问题

时间:2010-07-06 19:56:19

标签: c# c#-3.0

我注意到IEnumerable(Generics)需要实现两种方法:

1。 IEnumerator<T> GetEnumerator()

2。 IEnumerable.GetEnumerator()方法

http://msdn.microsoft.com/en-us/library/19e6zeyy.aspx

什么是#2 以及我应该如何定义/实施

从我玩一些代码开始,似乎在foreach循环中调用了IEnumerator GetEnumerator()。 #2 IEnumerable.GetEnumerator在哪里发挥作用?

我正在完成配方6.1在Oreilly的C#3.0 Cookbook中创建一个泛型类型的迭代器,我收到一个错误,因为#2没有实现(它没有包含在配方代码中)。

谢谢!

7 个答案:

答案 0 :(得分:9)

第一个是通用的GetEnumerator,而第二个是非泛型的。它们在功能上完成相同的工作,但非泛型只能返回object类型。

实现这些的最简单方法是实现通用版本,然后为非泛型提供:

IEnumerator IEnumerable.GetEnumerator() {
   return GetEnumerator();
}

答案 1 :(得分:2)

非通用的IEnumerable接口用于反向兼容,它还以非通用方式访问通用IEnumerable接口非常有用。

你只能实现IEnumerable.GetEnumerator成员,而只是明确实现其他界面,如

IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); /*generic method call*/ }

答案 2 :(得分:1)

#2是来自GetEnumerator接口的IEnumerable方法的显式非泛型实现。您的示例中的#1是GetEnumerator()接口的IEnumerable<T>实现。

IEnumerable.GetEnumerator()可以调用与IEnumerable相同的底层代码,它不是强类型的(返回对象而不是强类型的IEnumerator)。

答案 3 :(得分:1)

您只需要定义泛型(在我的示例中返回String),然后告诉非泛型GetEnumerator方法调用泛型GetEnumerator(返回Object。)

class Foo : IEnumerable<string>
{
    public IEnumerator<string> GetEnumerator()
    {
        foreach (string value in new[] { "a", "b", "c" })
        {
            yield return value;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

答案 4 :(得分:1)

第二个是针对.NET v1.1编写的代码,它不了解泛型。

通常,您只需返回通用GetEnumerator()

中的值
IEnumerator IEnumerable.GetEnumerator()
{
     return GetEnumerator();
}

答案 5 :(得分:0)

要实现第二个接口,请执行一个只调用泛型接口的隐式实现的显式实现。像

这样的东西
class FooCollection : IEnumerable<Foo>, IEnumerable
{
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<Foo> GetEnumerator()
    {
        // return enumerator
    }
}

编辑:从IEnumerable继承是多余的,但是这个答案表明,当您继承IEnumerable<T>时,两个接口都将被实现,因为IEnumerable<T>派生自IEnumerable {{1}}。

答案 6 :(得分:0)

通常你不应该再自己实现IEnumerable了。框架中有许多内置类,实现此接口有多种不同的方式来满足99%的需求。

但是,如果你愿意,IEnumerable,GetEnumerator()方法是一个将IEnumerator对象返回给调用foreach的客户端的方法。这个Ienumerator对象是跟踪集合中哪个元素是“下一个”的对象“当foreach”迭代“时,将返回一个。要使其工作,您必须定义一个将成为Enumerator的类(它必须实现IEnumerator,或者通常是IEnumerator)

作为示例(对于PersonCollection)

public IEnumerator GetEnumerator() { return new myTypeEnumerator(this); }
public class myTypeEnumerator : IEnumerator
{
    int nIndex;
    PersonCollection pers;
    public myTypeEnumerator(PersonCollection myTypes) 
     { pers = myTypes; nIndex = -1; }
    public bool MoveNext() { return (++nIndex < pers.alPers.Count); }
    public object Current { get { return (pers[nIndex]); } }
    public void Reset() { nIndex = -1; }
}

这个和通用版本之间的唯一区别是通用版本是强类型的:

public IEnumerator<T> GetEnumerator() { return new myTypeEnumerator<T>(this); }
public class myTypeEnumerator<T> : IEnumerator<T>
{
    int nIndex;
    IList<T> tList;
    public myTypeEnumerator(IList<T> listOfTs) 
     { 
        tList = listOfTs; 
        nIndex = -1; 
     }
    public bool MoveNext() { return (++nIndex < tList.Count); }
    public T Current { get { return (tList[nIndex]); } }
    public void Reset() { nIndex = -1; }
}