I have a class tha开发者_如何学编程t implements IEnumerator<string>
. See below:
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(); } }
}
Besides the fact that .Current property exists on both the IEnumerator<T>
interface and the IEnumerator
interface (which IEnumerator<T>
inherits), what's the point of implementing it? As seen above it's not even called.
IEnumerator<T>
implements IEnumerator
, so at the most basic level you have to fulfill the contract.
Specifically as to why - what happens if someone does this:
((IEnumerator)yourInstance).Current
They (usually) should expect to get a loosely-typed copy of the same value/reference returned from IEnumerator<T>
's implementation. So in most cases, just return this.Current
and don't worry about it :)
(FYI - returning this.Current
is also good practice because it follows DRY and SRP - let the strongly-typed version of Current deal with the implementation details of what Current actually is.)
The reason is that IEnumerator<T>
inherits IEnumerator
so when you inherit from IEnumerator<T>
you implicitly also inherit from IEnumerator
. If you advertise an interface you should also provide an implementation for that interface even if you never intend to use it.
The compiler requires you to implement all virtuals because it cannot possibly know which ones will be called when some unanticipated assembly loads your assembly at some point in the unknown future. By inheriting from an interface, you are "signing a contract" which promises that you will implement all its members. The compiler holds you to that agreement so that other assemblies will be able to rely on it.
The purpose of the interface feature is to enable your class to tell any other assembly, any where, any time, "this is what you can ask me to do". If you want to advertise a lesser capability, define a new interface that provides only the partial functionality you want, and implement that instead.
Of course, all of this is industrial-strength stuff. It's more than you need for your code right now. But C# is meant to be useful for doing serious stuff, not just toys.
As for the two different, near-identical overrides: You have to overrides both Current properties because they are essentially different: One is a generic returning T; the other is non-generic returning Object. You can always treat a String reference as a reference to Object, but that doesn't go both ways. And then what about value types? T is not constrained to be a class. Sure, the compiler could hypothetically figure all this out for you and let you off the hook in cases where the two are fungible, but it doesn't, and I'm not convinced it should. If you want C++, you know where to find it.
精彩评论