【问题标题】:Troubles implementing IEnumerable<T>实现 IEnumerable<T> 的麻烦
【发布时间】:2012-02-04 07:54:10
【问题描述】:

我正在尝试编写自己的(简单)List 实现。这是我到目前为止所做的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace provaIEnum
{
    class MyList<T> : IEnumerable<T>
    {
        private T[] _array;
        public int Count { get; private set; }

        public MyList() { /* ... */ }
        public void Add(T element) { /* ... */ }

        // ...

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < Count; i++)
                yield return _array[i];
        }
    }

我收到关于 GetEnumerator 的错误:

'provaIEnum.Lista' 没有实现接口成员 'System.Collections.IEnumerable.GetEnumerator()'。 'provaIEnum.Lista.GetEnumerator()' 无法实现 'System.Collections.IEnumerable.GetEnumerator()' 因为它没有 具有匹配的返回类型“System.Collections.IEnumerator”。

我不确定我是否理解 VS 试图告诉我的内容,并且我不知道如何解决它。

感谢您的宝贵时间

【问题讨论】:

  • 请注意,您不应该这样编写枚举器,因为目前您可以在 foreach 中修改内部数组(在 foreach 中调用 Add 不会导致异常)。 See
  • @nawfal 好点,虫子一直在看着我们;)

标签: c#


【解决方案1】:

我也遇到了类似的问题,虽然我也实现了 IEnumerable 和 IEnumerable。我使用的是自定义类型(Person 类)而不是泛型类型 T。 对我来说,原因是命名空间没有包含在文件的顶部。

using System.Collections; 

添加命名空间后对我来说很好。

【讨论】:

    【解决方案2】:

    您还需要实现非泛型 GetEnumerator 方法:

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    

    由于IEnumerable&lt;T&gt; 接口扩展了IEnumerable,因此您必须实现两者上声明的方法。

    【讨论】:

    • 显式接口实现不能有访问修饰符
    【解决方案3】:

    由于您的类MyList&lt;T&gt; 继承了IEnumerable&lt;out T&gt;,后者又继承了非泛型IEnumerable,因此您需要实现两个方法:

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
            {
                throw new NotImplementedException();
            }
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                throw new NotImplementedException();
            }
    

    一个简单的方法是当你声明你的类时:

    class MyList<T> : IEnumerable<T>
    

    右键单击IEnumerable&lt;T&gt; 文本并从上下文菜单中选择实现接口> 显式实现接口

    【讨论】:

      【解决方案4】:

      您必须实现 GetEnumerator() 的两个重载。一个来自IEnumerable&lt;T&gt; 并返回IEnumerator&lt;T&gt;。另一个来自 IEnumerable 并返回 IEnumerator。覆盖应该如下所示:

      IEnumerator IEnumerable.GetEnumerator()

      这是因为IEnumerable&lt;T&gt; 实现了IEnumerable

      【讨论】:

        【解决方案5】:

        添加如下方法:

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
        

        【讨论】:

          【解决方案6】:

          更仔细地阅读错误信息;它准确地告诉你你必须做什么。你没有实现System.Collections.IEnumerable.GetEnumerator

          当您实现通用 IEnumerable&lt;T&gt; 时,您还必须实现System.Collections.IEnumerable 的GetEnumerator。

          这样做的标准方法是:

          public IEnumerator<T> GetEnumerator () { whatever }
          System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
          {
              return this.GetEnumerator();
          }
          

          【讨论】:

            【解决方案7】:

            由于IEnumerable&lt;T&gt; 实现了IEnumerable,因此您还需要在具有GetEnumerator 方法的非泛型版本的类中实现此接口。为避免冲突,您可以显式实现它:

            IEnumerator IEnumerable.GetEnumerator()
            {
                // call the generic version of the method
                return this.GetEnumerator();
            }
            
            public IEnumerator<T> GetEnumerator()
            {
                for (int i = 0; i < Count; i++)
                    yield return _array[i];
            }
            

            【讨论】:

            • 谢谢,我不知道 IEnumerable 实现了 IEnumerable(虽然听起来很明显:P)
            • 因为你没有用System.Collections.明确限定IEnumeratorIEnumerable.GetEnumerator,如果你没有using System.Collections,这将失败,说(非常无助)IEnumerator需要一个通用的论据!
            • @PJTraill 此评论是正确答案(IEnumerator 需要完全合格才能解决与其通用变体冲突)。
            • ^ 不,PJTraill 的评论不是“正确答案”,达林给出了正确答案。您需要正确的 using 语句,否则需要完全限定接口名称,这是一个很好的观点,但很偶然。
            猜你喜欢
            • 2016-11-24
            • 1970-01-01
            • 1970-01-01
            • 2014-12-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-30
            • 1970-01-01
            相关资源
            最近更新 更多