【问题标题】:Benefit of Enumerables枚举的好处
【发布时间】:2017-05-08 01:10:26
【问题描述】:

我很难理解 IEnumerable 的好处。我了解 Enumerables 允许将执行推迟到以后。

请在此处查看示例:https://msdn.microsoft.com/en-us/library/system.collections.ienumerable(v=vs.110).aspx。在此示例中,该数组已填充到主类中,然后注入到 IEnumerable 类中。因此,这似乎消除了将执行推迟到以后的优势。我在这里错过了什么?

【问题讨论】:

  • 优点是 every 接口尽可能为调用者提供最少的信息。因此,与其对成员说“我需要一个数组才能正常工作”,您还可以说:“我需要某种可以枚举的集合”。所以不管它实际上是一个数组、一个列表还是 en(无尽)流。
  • IEnumerable<T> 主要是关于能够遍历T 的零个或多个实例 - 允许延迟执行的枚举没有任何隐含意义。然而,碰巧的是,LINQ 提供了一组操作符,这些操作符确实允许对枚举进行延迟执行。这是两个不同的东西。

标签: c# ienumerable ienumerator


【解决方案1】:

您引用的文档只是一个您如何实现它,而不是最有效的方式。当然,显示的实现根本没有用,因为正如您所说,数组已经被构造并且可以在其自身上枚举。

通过实现IEnumerable,该示例最多可用于展示自定义类型如何像集合一样工作。当然,这个非常通用的接口可用于在您不需要特定集合类型知识的各种地方调用,但示例中没有显示。

枚举器用于从头到尾遍历一组数据。您无法读取上一个项目,因为它已经被丢弃(例如需要从远程位置下载非常大的文件的迭代器,您可能不想缓存它们)。

【讨论】:

  • 有没有更好的例子可以推荐,它展示了如何更有效地使用它?谢谢
  • 也许this documentation on yield return 有,但我现在想不出其他来源。
  • 提示 Yield 关键字(我有一段时间没用过)在这里很有帮助。如果某样东西要表现得像一个集合,那么它肯定应该是一个集合吗?
  • 并非总是如此。它可以是一个类似于集合的流,其中项目被立即获取并丢弃。
  • “立即获得并丢弃”。我喜欢。请将其添加到您的答案中。然后我会标记你的答案。添加后告诉我。
【解决方案2】:

IEnumerable 的一个例子是延迟执行。

我认为使用 IEnumerable 的最大优势是:

  1. 您可以在不知道如何迭代的情况下迭代集合(集合是否有索引器?我应该如何迭代树?等等)。

  2. 您可以迭代集合的一部分 - 考虑找到满足您条件的第一个元素。

  3. 延迟执行 - 您可以过滤集合,一旦您遍历 IEnumerable(使用 ForEach\ToList 等),真正的过滤就会发生。

【讨论】:

  • @HimBromBeere 不。但在拥有 IEnumerable 接口之前,您需要知道如何迭代集合和其他可枚举的类。
【解决方案3】:

IEnumerable 的主要目的是不是将执行推迟到以后。 IEnumerable 的目的是提供一种迭代对象各部分的方法。这些部分可以是列表的项目,但它们也可以是(例如)string 的字符。 IEnumerable 接口之所以存在,是因为并非每个允许对其部分进行迭代的类都是集合或列表(例如string),而IEnumerable 提供了一个最小接口来实现这一点,而无需实现完整的@987654327 @ 或IList

IEnumerable 的主要和最重要的消费者是 foreach 语句,它从 time.NET 开始就存在。直到后来,LINQ 才出现了带有 Enumerable 类的 LINQ,该类也建立在 IEnumerable(或更准确地说是在 IEnumerable<T>)接口之上。

说到 LINQ,您在问题中提到的延迟执行确实是 LINQ 的一个关键特性。这意味着您定义的查询在执行IEnumerable 的迭代之前不会执行。这使您可以在执行查询之前进一步细化查询。

这种延迟执行虽然只涉及IEnumerable 如何使用,而不是它做了什么。延迟执行意味着您在定义 IEnumerable 时不会开始迭代它,而是在程序中的不同点开始迭代,例如 foreachToList 等。

【讨论】:

  • 我不确定string 是一个很好的反例。 string 只不过是 chars 的数组。否则,您将在其余部分中脱颖而出。
  • @gmiley - 这就是 Sefe 的意思。他指出stringchar 的可枚举。他是对的。
  • @gmiley:字符串实际上与字符数组不同(即使内部存储在char[] 中)。主要区别在于char[]IList,而string 不是。这就是我选择这个例子的原因,因为string只是IEnumerable,甚至不是ICollection
  • 我会给出一个创建一个实现IEnumerable 的类的示例,该类创建一个枚举类属性的IEnumerator。如果您愿意,我可以编辑您的答案以将该示例添加到底部,您可以按照自己的喜好对其进行修改。我不会更改您的答案的任何其他内容,只是觉得这将是一个很好的补充。
  • @gmiley:要完全实现 IEnumerable 接口,如果对象在枚举期间发生更改(通常使用枚举器版本),您需要抛出 InvalidOperationException,因此这并不像看起来那么简单(并且可能对OP来说太多了)。也许是进一步阅读的链接?
【解决方案4】:

是否推迟评估是一种设计选择,但 IEnumerable 并没有强制要求。一些 Linq 输出查询(如 Where 和 Select)延迟评估,而 Dictionary 或 List 等其他集合则不会。

当您需要从集合中获取的唯一信息是能够“枚举”元素时,您应该使用 IEnumerable。

假设您要为泛型集合实现 ToString 方法,其中对象有自己的 ToString。如果您接受 IEnumerable 而不是数组,则可以将 List 或 Set 作为参数传递,而无需更改任何代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多