为什么我在实现IEnumerator <t>?</t>的类中需要IEnumerator.Current

时间:2011-03-02 18:53:53

标签: c# .net ienumerator

我有一个实现IEnumerator<string>的类。见下文:

public class MyClass : IEnumerator<string>
{
    public bool MoveNext()
    {
        //....
    }

    //Implement other required methods....

   //Confusion lies below:
   public string Current { get { return this.CurrentLine; } }

   //Why do I need to implement IEnumerator.Current?!  In my tests, it's not even called    during my iteration
   object IEnumerator.Current { get { throw new NotImplementedException(); } }

}   

除了IEnumerator<T>接口和IEnumerator接口(IEnumerator<T>继承)都存在.Current属性之外,实现它的重点是什么?如上所述,它甚至没有被召唤。

3 个答案:

答案 0 :(得分:15)

IEnumerator<T>实施IEnumerator,因此在最基本的级别,您必须履行合同。

特别是为什么 - 如果有人这样做会发生什么:

((IEnumerator)yourInstance).Current

他们(通常)应该期望获得从IEnumerator<T>实现返回的相同值/引用的松散类型的副本。因此,在大多数情况下,只需返回this.Current并且不要担心:)

(仅供参考 - 返回this.Current也是一种很好的做法,因为它遵循DRY和SRP - 让强类型版本的Current处理Current实际上的实现细节。)

答案 1 :(得分:3)

原因是IEnumerator<T>继承了IEnumerator,因此当您从IEnumerator<T>继承时,您隐含地也会继承IEnumerator。如果您宣传界面,即使您从未打算使用它,也应该为该界面提供实现。

答案 2 :(得分:1)

编译器要求您实现所有虚拟,因为当一些未预料到的程序集在未知未来的某个时刻加载程序集时,它无法知道将调用哪些虚拟。通过继承接口,您将“签订合同”,承诺您将实现其所有成员。编译器会阻止您使用该协议,以便其他程序集能够依赖它。

界面功能的目的是让您的班级能够告诉任何其他组件,任何地点,任何时间,“这是您可以要求我做的事情”。如果要宣传较小的功能,请定义一个仅提供所需部分功能的新界面,并实现该功能。

当然,所有这些都是工业强度的东西。这比你现在需要的代码还要多。但是C#对于做一些严肃的事情非常有用,而不仅仅是玩具。

至于两个不同的,几乎相同的覆盖:你必须覆盖两个Current属性,因为它们本质上是不同的:一个是泛型​​返回T;另一种是非泛型的返回Object。您始终可以将String引用视为对Object的引用,但这不是双向的。那么价值类型呢? T不限于是一个类。当然,编译器可以假设你想出这一切,并让你在两个可互换的情况下摆脱困境,但事实并非如此,我不相信它应该。如果你想要C ++,你知道在哪里找到它。