The behavior of the generic enumerator is undefined, anything is possible and it is ultimately up to the collection type to define what undefined is going to mean.
But they can do something reasonable beyond throwing, the generic enumerators know the type of the collection object. So they can return default(T)
.
The non-generic enumerators don't have that luxury, they could only return null or new object()
. ArrayList in fact has code that reserves a static object for just this purpose. But doesn't actually use it, looks like they changed their mind after usability testing. Returning either is going to make the client code fail with a very unpleasant exception, NullReferenceException or InvalidCastException. Exceptions that can also be raised in normal usage of those collections so there's very little hint to the actual cause of the mishap. So they don't, they throw InvalidOperationException instead.