C# 关于IEnumerable<;T>;

C# 关于IEnumerable<;T>;,c#,c#-3.0,C#,C# 3.0,我注意到IEnumerable(泛型)需要实现两种方法: 1IEnumerator GetEnumerator() 2IEnumerable.GetEnumerator()Method () 什么是#2以及我应该如何定义/实施这一点 从我玩的一些代码来看,似乎IEnumerator GetEnumerator()是在foreach循环中调用的。 #2 IEnumerable.GetEnumerator在哪里发挥作用 在Oreilly的C#3.0食谱中,我浏览了recipe 6.1,在泛型类型上创

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

1<代码>IEnumerator GetEnumerator()

2
IEnumerable.GetEnumerator()
Method

()

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

从我玩的一些代码来看,似乎IEnumerator GetEnumerator()是在foreach循环中调用的。 #2 IEnumerable.GetEnumerator在哪里发挥作用

在Oreilly的C#3.0食谱中,我浏览了recipe 6.1,在泛型类型上创建了迭代器,我遇到了一个错误,因为#2没有实现(它没有包含在配方代码中)

谢谢大家!

#2是
IEnumerable
接口中
GetEnumerator
方法的显式非泛型实现#在您的示例中,1是针对
IEnumerable
接口的
GetEnumerator()
的实现


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

第一个是通用的GetEnumerator,而第二个是非通用的。它们的功能相同,但非泛型只能返回
对象
类型

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

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

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

class FooCollection : IEnumerable<Foo>, IEnumerable
{
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<Foo> GetEnumerator()
    {
        // return enumerator
    }
}
class FooCollection:IEnumerable,IEnumerable
{
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
公共IEnumerator GetEnumerator()
{
//返回枚举器
}
}

Edit:
IEnumerable
继承是多余的,但是这个答案表明,当您继承
IEnumerable
时,这两个接口都要实现,因为
IEnumerable
派生自
IEnumerable

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

类Foo:IEnumerable
{
公共IEnumerator GetEnumerator()
{
foreach(新[]{“a”、“b”、“c”}中的字符串值)
{
收益回报值;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
返回GetEnumerator();
}
}

非泛型IEnumerable接口用于后端兼容性,它还提供了以非泛型方式访问泛型IEnumerable接口的非常有用的功能

您只能实现IEnumerable.GetEnumerator成员,只需明确实现其他接口,如

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

第二个是为.NETV1.1编写的代码,它不理解泛型

通常,您只需要让它从泛型GetEnumerator()返回值


一般来说,您不需要自己实现IEnumerable。框架中有许多内置类,它们实现这个接口,并通过各种不同的方式满足99%的需求

但是,如果需要,IEnumerable,GetEnumerator()方法将向调用foreach的客户端返回IEnumerator对象。此IEnumerator对象是跟踪集合中哪个元素是foreach“迭代”时要返回的“下一个”元素的对象。为此,必须定义一个类作为该枚举器(它必须实现IEnumerator,或一般称为IEnumerator)

例如(对于个人集合)

public IEnumerator GetEnumerator(){返回新的myTypeEnumerator(this);}
公共类myTypeEnumerator:IEnumerator
{
int-nIndex;
个人收集;
公共myTypeEnumerator(PersonCollection myTypes)
{pers=myTypes;nIndex=-1;}
public bool MoveNext(){return(++nIndex
此版本与泛型版本之间的唯一区别在于泛型版本是强类型的:

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; }
}
public IEnumerator GetEnumerator(){返回新的myTypeEnumerator(this);}
公共类myTypeEnumerator:IEnumerator
{
int-nIndex;
IList-tList;
公共myTypeEnumerator(IList listOfTs)
{ 
tList=列表OFTS;
nIndex=-1;
}
public bool MoveNext(){return(++nIndex
Wow可能重复。你们太棒了!谢谢你的帮助。是的,我所做的是在非泛型方法中返回GetEnumerator()。@x0n,这部分是好的,我的代码在接口继承声明部分是多余的,但它确实显示了发生了什么。实现通用接口需要实现非通用接口。但准确地说,
IEnumerable
并没有实现
IEnumerable
。不可能。回顾过去,我并不是想让你知道一点——一个简单的评论就足够了。我来倒过来。更新:除非您编辑您的问题以修复冗余,否则我无法撤销分数;-)是的,“implement”是个错误的动词。“源自”或“继承”是我的意思。Doh。
IEnumerator IEnumerable.GetEnumerator()
{
     return GetEnumerator();
}
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; }
}