【问题标题】:what is IEnumerable in .net.net 中的 IEnumerable 是什么
【发布时间】:2010-06-10 13:23:45
【问题描述】:

.net 中的 IEnumerable 是什么?

【问题讨论】:

  • 说实话,MSDN 上的定义对于初学者来说是非常可怕的,当你只想做一个 foreach 时。
  • 虽然我能理解为什么它被关闭了,但在 MSDN 不是很清楚之后,我从谷歌来到了这个,答案真的帮助了我。如果可以的话,我会投票支持重新开放......当谷歌搜索“什么是 IEnumerable”时,这会很重要,我相信其他人会发现它很有帮助。

标签: .net ienumerable


【解决方案1】:

它是……可以循环播放的东西……。这可能是 List 或 Array 或(几乎)任何其他支持 foreach 循环的东西。它适用于当您希望能够使用带有 foreach 循环的对象,但您不知道自己正在处理的具体类型是 Array、List 还是自定义对象时。

这是第一个优势:如果您的方法接受 IEnumerable 而不是数组或列表,它们会变得更强大,因为您可以向它们传递更多不同类型的对象。

现在让 IEnumerable 真正脱颖而出的是迭代器块(C# 中的 yield 关键字)。迭代器块像 List 或 Array 一样实现 IEnumerable 接口,但它们非常特殊,因为与 List 或 Array 不同,它们通常一次只保存单个项目的状态。因此,例如,如果您想遍历一个非常大的文件中的行,您可以编写一个迭代器块来处理文件输入。那么你一次在内存中永远不会有超过一行的文件,如果你更早地完成循环(也许它是一次搜索并且你找到了你需要的东西)你可能不需要读取整个文件。或者,如果您正在读取大型 SQL 查询的结果,您可以将内存使用限制为单个记录。

另一个特点是这个评估是惰性的,所以如果你正在做复杂的工作来评估你读取的枚举,那么直到它被要求时才会发生这种工作。这是额外的好处,因为通常(例如,再次搜索)您会发现您可能根本不需要做这项工作。

您可以将 IEnumerable 视为一个即时列表。

【讨论】:

  • IEnumarable 的关键是支持集合是not enumerated,直到专门扩展,无论是通过索引器的 foreach 还是访问器。不幸的是,IEnumarable 似乎被盲目地用作最低接口,这会导致异步数据操作出现问题(例如,在 GarbageCollected 上下文上执行 SQL)。我想说ICollection 是您所说的除了“惰性评估”之外的所有内容,我们应该使用它,特别是如果数据已经被枚举过一次!
  • 最简单的简单英语解释,脱帽致敬!
  • 我认为 IEnumerable 的名字很糟糕。在数学上和计算中,可枚举是映射到可数集的任何东西。所以在.net 之外,一个 IObservable 可能是可枚举的。在 .NET 中,IEnumerable 被认为是 IObservable 的双重对立面,具有拉式与推式二元性。 IEnumerable 的用意似乎是 Java 所谓的 Iterable,在我看来这是一个更好的名称。
【解决方案2】:

它是由 .NET 中的 Collection 类型实现的接口,提供 Iterator pattern。还有通用版本IEnumerable<T>

在实现 IEnumerable 的集合中移动的语法(你很少看到,因为有更漂亮的方法)是:

IEnumerator enumerator = collection.GetEnumerator();

while(enumerator.MoveNext())
{
    object obj = enumerator.Current;
    // work with the object
}

这在功能上等同于:

foreach(object obj in collection)
{
    // work with the object
}

如果集合支持索引器,您还可以使用经典的 for 循环方法对其进行迭代,但迭代器模式提供了一些不错的附加功能,例如为线程添加同步的能力。

【讨论】:

  • 注意,这里显示的语法取决于 C# 5 中的 foreach 等价物。在 C# 4 及更早版本中,object obj; 在 while 循环之外声明,这会在处理捕获变量(如匿名函数)时改变循环的行为。
  • tech-over-tech 的回答只会带来更多的困惑和挫败感。
【解决方案3】:

首先它是一个接口。根据MSDN的定义是

公开枚举器,它支持 对非泛型的简单迭代 收藏。

用很简单的方式说,任何实现这个接口的对象都会提供一种获取枚举器的方法。以foreach 为例,使用枚举器。

List 实现了 IEnumerable 接口。

    // This is a collection that eventually we will use an Enumertor to loop through
    // rather than a typical index number if we used a for loop.
    List<string> dinosaurs = new List<string>();

    dinosaurs.Add("Tyrannosaurus");
    dinosaurs.Add("Amargasaurus");
    dinosaurs.Add("Mamenchisaurus");
    dinosaurs.Add("Deinonychus");
    dinosaurs.Add("Compsognathus");

    Console.WriteLine();

    // HERE is where the Enumerator is gotten from the List<string> object
    foreach(string dinosaur in dinosaurs)
    {
        Console.WriteLine(dinosaur);
    }

    // You could do a 
    for(int i = 0; i < dinosaurs.Count; i++)
    {
        string dinosaur = dinosaurs[i];

        Console.WriteLine(dinosaur);
    }

foreach 看起来更干净。

【讨论】:

    【解决方案4】:

    简短的回答是,你可以在上面使用foreach

    【讨论】:

    • 您可以使用 GetEnumerator 方法遍历任何内容。它不必支持 IEnumerable。
    • 是的,但大多数时候IEnumerable &lt;==&gt; foreach
    • 我想没有人真正知道我们为什么要使用它们,而是告诉定义比较我们何时以及为什么应该使用它们
    【解决方案5】:
    • 它是一个基础接口,使我们能够循环或迭代集合。

    • 关于 IEnumerable 最重要的一点是,当您遍历一个对象或 集合,它一次只保存一个项目的状态。

    • 当您迭代大对象或集合时,它具有良好的性能 因为它不会将整个对象加载到内存中以进行迭代。为了 例如,假设您决定逐行读取一个大文件并在 那,因此您可以编写自己的ReaderEnumrable 来读取您的文件 具有高性能。

    • 当您使用 IEnumerable 编写查询时,您正在使用延迟的优势 执行和您的查询在访问时运行。

    • 每次你运行你遍历一个集合,一个不同的 集合创建。例如在以下代码中,每次listOfFiles 访问ListOfAllFiles 时再次执行。

      public static void Main()
      {
          var listOfFiles = ListOfAllFiles();
      
          var filesCount = listOfFiles.Count();
          var filesAny = listOfFiles.Any();
          var fileIterate = listOfFiles.Select(x => x.FullName);
      }
      
      private static IEnumerable<FileInfo> ListOfAllFiles()
      {
          foreach(var file in Directory.EnumerateFiles(Environment.CurrentDirectory))
          {
              yield return new FileInfo(file);
          }
      }
      

    【讨论】:

    • 您的大多数假设都是“收益回报”的特征,而不是具体的 IEnumerable。 IEnumerable 只是提供迭代方式的接口,仅此而已。
    • 你在使用yield return时使用IEnumerable,因此它们是完全相关的。
    猜你喜欢
    • 2011-02-15
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 2011-08-06
    • 2010-11-19
    • 1970-01-01
    相关资源
    最近更新 更多