【问题标题】:yield return works only for IEnumerable<T>?yield return 仅适用于 IEnumerable<T>?
【发布时间】:2010-11-07 10:39:35
【问题描述】:

当返回类型为IGrouping&lt;TKey, TElement&gt;IDictionary&lt;TKey, TValue&gt; 时,我可以使用yield return 吗?

【问题讨论】:

标签: c# .net ienumerable


【解决方案1】:

不,只是 ienumerable :-)

【讨论】:

    【解决方案2】:

    我不这么认为。虽然documentation 没有准确地拼出它,但它的措辞方式暗示它只能在方法的返回类型为IEnumerableIEnumerable&lt;T&gt; 时使用。给定IEnumerable(将使用yield return 从您的方法返回),您也许可以编写一个实现IGrouping 的类,但这实际上是唯一的选择。

    【讨论】:

    • 语言规范将其拼写出来...参见 ECMA 334 中的 8.18
    【解决方案3】:

    不,因为迭代器块只是编译器为您构建的状态机。此功能允许您“让步”并将项目作为序列的一部分。

    如果返回类型不是IEnumerable&lt;T&gt;(例如IDictionary),编译器必须生成方法来实现该接口,此时它没有多大意义,因为您将使用集合而不是序列。

    【讨论】:

      【解决方案4】:

      但是,您可以返回类似于字典的 IEnumerable&lt;KeyValuePair&lt;K,V&gt;&gt;。然后你会产生返回 KeyValuePairs。你甚至可以用另一种从返回中创建字典的方法来包装它。第一种方法唯一不能保证的是键的唯一性。

      【讨论】:

      • 那么你会失去 O(1) 的访问时间,并且必须循环遍历每个 KVP 以找到正确的密钥,最坏的情况是 O(n) 次。
      【解决方案5】:

      yield return 仅适用于 4 种情况:

      • IEnumerable
      • IEnumerable&lt;T&gt;
      • IEnumerator
      • IEnumerator&lt;T&gt;

      这是因为它必须在内部构建一个状态机;字典(等)是不可能的。你当然可以只用return 一个合适的类型来代替。

      【讨论】:

      • 方便的文章在这里csharpindepth.com/articles/chapter6/… 如果你想自己实现 IEnumerable。
      • @Rory 是的,自己实现它是一个巨大的 PITA,我想不出任何“正常”的理由这样做,因为存在迭代器块。我有一些这样的,但这通常是为了兼容需要在 C# 1.2 编译器上构建的项目;不完全是“正常”的情况。
      • 同意,虽然 IGrouping 在某些情况下可能会很好,但使用 IEnumerable> 似乎更容易,因此您可以获得收益回报的魔力。
      【解决方案6】:

      答案:不可以。只有当返回类型为IEnumeratorIEnumerator&lt;T&gt;IEnumerableIEnumerable&lt;T&gt; 时,才能使用yield return 语句。

      来自C# 3.0 spec 的§8.14:

      yield 语句用于迭代器块(第 8.2 节)中,为迭代器的枚举器对象(第 10.14.4 节)或可枚举对象(第 10.14.5 节)生成一个值,或发出迭代结束的信号.

      从 §10.14.4:

      枚举器对象具有以下特征:

      1. 它实现了IEnumeratorIEnumerator&lt;T&gt;,其中T 是迭代器的产量类型。

      [...]

      从 §10.14.5:

      可枚举对象具有以下特征:

      1. 它实现了IEnumerableIEnumerable&lt;T&gt;,其中T 是迭代器的产量类型。

      [...]

      【讨论】:

        【解决方案7】:

        只需调用迭代器方法并在其后链接ToDictionaryGroupBy,您就会得到很多相同的东西。如果您需要从多个地方这样调用它,请将其放入单行包装器方法中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-04
          • 1970-01-01
          • 2011-12-09
          • 1970-01-01
          • 1970-01-01
          • 2012-01-03
          • 2011-04-20
          • 2011-03-10
          相关资源
          最近更新 更多