【问题标题】:What is the link between foreach and IEnumerable? [duplicate]foreach 和 IEnumerable 之间有什么联系? [复制]
【发布时间】:2014-01-31 01:09:34
【问题描述】:

foreach 语句为实现System.Collections.IEnumerableSystem.Collections.Generic.IEnumerable<T> 接口的数组或对象集合中的每个元素重复一组嵌入语句。

我知道如果我们想在一个对象集合上使用 foreach,我们需要在它上面实现 IEnumerable。

我想了解在 IEnumerable 中实现如何启用“foreach”的使用?

IEnumerable的源码好像只有一个函数'GetEnumerator',显然没有实现,因为IEnumerable是一个接口——那么foreach关键字究竟是如何使用IEnumerable接口进行枚举的呢?

编辑: 也试图在这种情况下理解它:

IEnumerable<Int> myNumbers = new IEnumerable<Int>();

这里调用/使用了哪个 GetEnumerator()?

编辑 2:

所以答案似乎是:
1:DuckTyping --(感谢@Alexei Levenkov。我接受@horrorcat 作为答案,因为我只能接受一个:))
2. 我在尝试创建接口的具体实例时犯了一个明显的错误(在我的问题的第二部分)——(感谢@Gary Vass)

【问题讨论】:

  • 它只是调用那个方法。
  • IEnumerable 的实现者实现了方法GetEnumerator(),foreach 调用该方法然后使用生成的IEnumerator 对元素进行迭代。
  • 也许你应该阅读Interfaces (C# Programming Guide)
  • 您不能创建接口的具体实例。

标签: c# foreach ienumerable ienumerator


【解决方案1】:

IEnumerable.GetEnumerator() 返回一个枚举器对象(它实现了 IEnumerator)。它有一个返回当前项目的属性“Current”,以及一个将枚举数推进到下一个项目的方法“MoveNext()”。

这就是执行 foreach 所需的所有 foreach 循环。它只是将“Current”属性分配给一个变量,然后每次执行 .MoveNext()。

通常,当您在一个类上实现 IEnumerable 时,您就知道源代码的来源。所以如果你有这样的课程

public class MyEnumerable
{
    private List<string> items;
}

IEnumerable 的实现如下所示

public class MyEnumerable : IEnumerable<string>
{
    private List<string> items;

    public IEnumerator<string> GetEnumerator()
    {
        return items.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return items.GetEnumerator();
    }
}

请注意,枚举器来自列表对象,因此您不必担心创建枚举器(尽管您可以通过实现 IEnumerator 来实现)

【讨论】:

  • 谢谢,这很有意义。现在,如果我像这样使用 IEnumerable: IEnumerable sel = someFunctionWhichReturnsAnIenumerable() (或 linq 语句) 那么 foreach 没有 GetEnumerator 的实现,对吗? (因为 IEnumerable 源代码只有一个空定义 Getenumerator 而不是实现。那么它从哪里获得返回 IEnumerator 的 GetEnumerator 实现?
【解决方案2】:

foreach 调用IEnumerable.GetEnumerator()(如果集合实现了一个)或查找返回duck-typed matching iterator classGetEnumerator() 方法。

使用GetEnumerator() 调用的结果对元素进行迭代,将每个元素转换为foreach 的第一个参数中指定的类型。

【讨论】:

  • 如果 'collection does not implement one' 会发生什么?
  • @Gadam - 链接的答案包含详细信息 - 在这种情况下,它使用鸭子打字来查找必要的方法。
【解决方案3】:

正如 Lukazoid 所说,“IEnumerable 的实现者实现了 GetEnumerator() 方法,foreach 调用此方法,然后使用生成的 IEnumerator 对元素进行迭代。”

foreach 仅使用接口 IEnumerable/IEnumerable,我认为这是编写“只读”for 循环的 C# 捷径,您可以使用数据但不能编辑它。

我也在stackoverflow上找到了这个//which may make this question a dup

What's going on behind the scene of the 'foreach' loop?

【讨论】:

    【解决方案4】:

    Foreach 只是使用 IEnumerable 类型的语法糖。代码如下:

    foreach (var item in collection)
    {
        ...
    }
    

    被编译器翻译成类似:

    using (var enumerator = collection.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            var item = enumerator.Current;
            // loop contents here
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-31
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 2014-08-14
      • 1970-01-01
      相关资源
      最近更新 更多