【问题标题】:yield not working with custom enumerable/enumerator产量不适用于自定义可枚举/枚举器
【发布时间】:2015-04-19 00:29:34
【问题描述】:

最近我开始了一个爱好项目来重写集合结构,首先删除不通用的IEnumeratorIEnumerable,创建新的 IEnumerator/IEnumerable 基础接口。在我的新可枚举接口和普通接口之间创建转换时,我很快遇到了产量问题。

我的IEnumerable<T>IEnumerator<T> 与普通的完全相同,只是它们不是从非通用的继承而来。 为什么 yield 不适用于我的接口? foreach 确实适用于我的界面。

例子:

public static System.Collections.Generic.IEnumerable<T> ToMSEnumerable(this My.IEnumerable<T> enumerable)
{
    foreach (var item in enumerable) // enumerating my enumerable works
    {
        yield return item; // this works
    }
}

public static My.IEnumerable<T> ToMyEnumerable(this System.Collections.Generic.IEnumerable<T> enumerable)
{
    foreach (var item in enumerable) // obviously work
    {
        yield return item; // this is where its not working.
                           // I haven't touched this in a few day, so I don't remember
                           // the error message
    }
}

【问题讨论】:

  • 我很好奇 - 您的 My.IEnumerable&lt;T&gt; 与标准 IEnumerable&lt;T&gt; 有何不同?
  • @Enigmativity 它没有非泛型GetEnumerator()
  • 为什么这很重要?
  • @Enigmativity 接口的用户不必实现它吗?更好的类型安全性?
  • 为什么用户仍然需要实现它?考虑到内置集合和运算符的数量,这将是一件非常罕见的事情。

标签: c# yield


【解决方案1】:

您的foreach 可以工作,因为foreach uses duck-typing - 任何带有GetEnumerator 方法的东西都可以工作。这是因为 foreach 比泛型更老,所以这是实现它并获得强类型的唯一合理方法。

但是,迭代器方法比泛型更早,因此yield 在设计时考虑到了IEnumerable&lt;T&gt;。因此,yield需要

  • 返回类型必须为IEnumerableIEnumerable&lt;T&gt;IEnumeratorIEnumerator&lt;T&gt;

(https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx)

当然,你自己构建的可枚举类不在列表中。

【讨论】:

  • 每个真正“酷”的事情是GetEnumerator()返回的类型不需要是IEnumerator all,它检查的是一个名为MoveNext()的公共方法和一个公共属性命名为Current,如果它有这两个东西,它会很高兴地工作。
  • 不错的答案。考虑编辑问题以添加正确的错误消息,使其看起来不像删除的候选对象。
  • 我是这么想的。但似乎与集合周围的其他“鸭式打字”有点不一致。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
相关资源
最近更新 更多