首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么时候调用IEnumerable.GetEnumerator而不是IEnumerable<T>.GetEnumerator?

什么时候调用IEnumerable.GetEnumerator而不是IEnumerable<T>.GetEnumerator?
EN

Stack Overflow用户
提问于 2013-02-16 10:34:33
回答 3查看 2.5K关注 0票数 9

看看这段代码:

代码语言:javascript
复制
public class myWords : IEnumerable<string>
{
    string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries);

    public IEnumerator<string> GetEnumerator()
    {
        return f.Select(s => s + "2").GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return f.Select(s => s + "3").GetEnumerator();
    }
}

跑步:

代码语言:javascript
复制
 myWords m = new myWords();
 foreach (var s in m)
 {
     Console.WriteLine(s);
 }

产量

代码语言:javascript
复制
I 2
ve you2    // notice "2", so the generic Ienumerator has executed.

据我所知,非通用IEnumerator版本是为了兼容性.

问题:

  1. 在什么情况下将调用非泛型?
  2. 如何强制我的代码使用非泛型IEnumerator运行?
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-02 19:20:36

其他的回答有点漏掉了重点。

如果foreached的编译时类型有一个名为GetEnumerator的非泛型非静态方法,则接口根本不重要,该方法采用零参数。(此方法的返回类型可以是任何类型,泛型或非泛型:接口不重要。)

因此,调用第一个方法的原因是,这是public方法。

你可以改变这一点:

代码语言:javascript
复制
public class myWords : IEnumerable<string>
{
    string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries);

    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
        return f.Select(s => s + "2").GetEnumerator();
    }

    public IEnumerator GetEnumerator()
    {
        return f.Select(s => s + "3").GetEnumerator();
    }
}

要证明不需要接口,请尝试如下:

代码语言:javascript
复制
public class myWords // no interfaces!
{
    string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries);

    public IEnumerator GetEnumerator()
    {
        return f.Select(s => s + "3").GetEnumerator();
    }
}

但是,实现IEnumerable<>是明智的。然后,您的类型可以与Linq (IEnumerable<>上的扩展方法)一起使用,并且可以用作其他只需要IEnumerable<>的方法的参数。

此外,明智的做法是让返回非泛型IEnumerator的方法(或显式接口实现)直接调用返回IEnumerator<>的方法(或显式接口实现)。有两个不同的返回序列确实令人困惑(但是对于询问和回答事情是如何工作的问题来说,这是很好的)。

票数 4
EN

Stack Overflow用户

发布于 2013-02-16 10:38:46

当代码将类转换到非泛型接口时,将执行非泛型IEnumerator:

代码语言:javascript
复制
((IEnumerable)myWords).GetEnumerator(); // this calls the non-generic one

如果您将类传递给某些需要非泛型IEnumerator的遗留函数,则这主要是相关的。

因此,如果您有一个包含函数的库,并且将类传递给这个函数,它将使用非泛型IEnumerator。

代码语言:javascript
复制
DoSomeStuffWithAnIEnumerable(IEnumerable x)
{
   var foo = x.GetEnumerator();

   // or, as stackx said, an example with foreach:
   foreach (var foo2 in x)
   Console.WriteLine(foo2);
}


DoSomeStuffWithAnIEnumerable(new myWords());

请注意,简单地使用泛型IEnumerator实现非泛型是完全有效的:

代码语言:javascript
复制
public class myWords : IEnumerable<string>
{
    ....    
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

这样你就可以确定它们都有相同的效果。

票数 7
EN

Stack Overflow用户

发布于 2013-02-16 10:47:04

IEnumerable的非泛型版本是通过显式接口实现实现的。这意味着您只能通过转换到接口来调用显式实现的函数。

之所以显式实现IEnumerable,是因为除了返回类型之外,方法签名是相同的。

myWords显式转换为IEnumerable允许您调用非通用版本,如:(IEnumerable)myWords

C#指南解释了这是如何工作的:显式接口实现

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14909326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档