The non generic IEnumerator and the generic one

IEnumerator and its generic counterpart, IEnumerator<T> are rather old interfaces, one being there since .Net 1, the other since .Net 2 (with the arrival of generics). The generic inherits from the non generic one, IEnumerator being still here probably mostly for compatibility reason. Here’s their definition.

They are quite simple and self explanatory. The only interesting thing is that they both have a read only property called Current but with different return type. C# doesn’t let you override a method by changing the return type, so… how is that possible?

It’s possible because in that case, it’s not overriding, it’s hiding. If you look at the Current defined of the generic IEnumerator, you’ll see the new keyword. Here’s what the C# reference has to say about the new modifier.

When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version. Although you can hide members without using the new modifier, you get a compiler warning. If you use new to explicitly hide a member, it suppresses this warning.

What does it actually mean? In what is hiding different than overriding? Let’s try a small example.

Inheritance

If you run this sample, you’ll obviously get an output “woof woof”. It’s the base of object oriented programming. It doesn’t matter that your Dog is hiding inside an Animal variable, it’s still a dog and it will bark.

Hiding

Now, the more confusing hiding through the new keyword.

Now the output is different based on the variable type. Even though our object is still a dog, if the variable it’s in is an Animal, the Animal implementation of the Shout method is called. When it’s in a Dog variable, it’s the Dog implementation that is used because it’s hiding the Animal one… ouch. One important thing to grasp is that we’re using hiding for a reason, in a Dog object, both Shout methods exist! You can actually access it by prefixing with the Animal class name.

This goes without saying that this is incredibly confusing and should be used with extreme precaution, you should have a really good reason to do it, like for the IEnumerator<T> interface.