【问题标题】:Why does implementing 'IList<T>' require defining two 'GetEnumerator' methods?为什么实现 'IList<T>' 需要定义两个 'GetEnumerator' 方法?
【发布时间】:2010-12-10 16:38:22
【问题描述】:

当我实现IList&lt;T&gt; 时,我发现我需要定义两个 GetEnumerator 方法。一个返回IEnumerator 类型的值,而另一个返回IEnumerator&lt;T&gt;

我对这两种GetEnumerator 方法之间的区别有点困惑。虽然返回类型明显不同,但它们本质上不是保存相同的数据吗?

此外,为什么GetEnumerator 的两个版本都可以作为方法存在,而它们仅在返回类型上有所不同?这似乎违反了 C# 中的规则,该规则指定重载方法不能仅在返回类型上有所不同。

【问题讨论】:

    标签: c# .net list interface


    【解决方案1】:

    两者都应该返回相同的数据,是的。

    IEnumerator 来自 .Net v1.1,在引入泛型类型之前。 IEnumerator&lt;T&gt; 是 .Net v2 中添加的通用类型版本。

    “旧”版本 IEnumerator 已保留以保持兼容性,因此现在 IList&lt;T&gt; 实现了两者。

    两者的区别在于非泛型IEnumerator返回对象,而泛型IEnumerator&lt;T&gt;返回T。虽然,c# 编译器会为您插入一个强制转换,以便在 foreach 中使用非泛型 IEnumerator 似乎 是强类型的。

    泛型类型参数的存在足以让编译器区分这两个接口,但要实现这两个接口的类必须显式实现。

    【讨论】:

    • 不太正确,通用参数还不够——一个是显式实现的,另一个不是。
    • 我几乎不会在 foreach 循环魔术中调用 IEnumerator 的非通用使用。它只是尝试从对象转换为您指定的类型。如果失败,你会得到一个异常。
    • 接受解释向后兼容性问题。谢谢。
    • 这两个 IEnumerator 接口之间还有一个区别,除了它们返回的类型之外:如果没有 'Current' 项(如果枚举器在列表之前或之后),那么 IEnumerator.Current 是应该抛出异常,而 IEnumerator&lt;T&gt;.Current 应该返回 null 或默认值。如果您编写一个实现这两个接口的枚举器类,则在实现两个 Current 属性时需要小心。
    • msdn.microsoft.com/en-us/library/… 表示“如果对 MoveNext 的最后一次调用返回 false,则 Current 也会引发异常,这表示集合结束。”,而 msdn.microsoft.com/en-us/library/58e146b7.aspx 表示未定义。对象浏览器为非泛型显示了这一点:“System.InvalidOperationException:枚举器位于集合的第一个元素之前或最后一个元素之后。”查看List&lt;T&gt; 枚举器表明它遵循这些规则。
    【解决方案2】:

    这两个来自 IList 本身实现的不同接口,这就是为什么你必须同时实现这两个:

    public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
    

    因为Explicit Interface Implementation,它们都能够存在。

    【讨论】:

    • 感谢您的链接。这比什么都更有帮助。
    【解决方案3】:

    是的,两种方法都应该返回相同的数据。

    它们可以共存,因为它们是两个不同接口的一部分,IEnumerableIEnumerable&lt;T&gt;

    【讨论】:

      【解决方案4】:

      它们都可以存在,因为其中一个将被实现explicitly

      IEnumerator IEnumerable.GetEnumerator()
      {
      
      }
      

      如果你试图让它们都隐式定义,你会得到编译错误。

      是的,它们都应该返回相同的数据。

      您需要定义GetEnumerator 的两个版本,以满足派生IList&lt;T&gt; 的两个接口(@98​​7654324@ 和IEnumerable&lt;T&gt;)。然而,在实践中,您往往会发现GetEnumerator 的非泛型版本在大多数实现中只调用泛型版本。

      【讨论】:

        【解决方案5】:

        IList&lt;T&gt; 实现IEnumerable&lt;T&gt;IEnumerableGetEnumerator 的不同实现来自这些接口中的每一个。两者都应该返回相同的数据。

        【讨论】:

          【解决方案6】:

          IEnumerator 枚举对象,而 IEnumerator 枚举 T。对于第二个问题,第二个函数是完全限定的:

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()  
            {
          
            }
          

          public IEnumerator<T> GetEnumerator()
              {
          
              }
          

          【讨论】:

            猜你喜欢
            • 2011-04-13
            • 2014-01-09
            • 1970-01-01
            • 2011-04-04
            • 2015-01-02
            • 1970-01-01
            • 1970-01-01
            • 2021-08-25
            • 2015-04-15
            相关资源
            最近更新 更多