It is possible for implementations of IEnumerable(Of T) to return any items they see fit, for any reason whatsoever. It's pretty well expected that if one calls GetEnumerator twice on the same sequence of items, and then proceeds to cycle through both enumerators, they should either yield the same items in the same order or throw an exception. There are a number of routines that accept an IEnumerable(Of T) and will fail badly if given one that does not abide by such a contract.
If I had my druthers, IEnumerable would have been split into a family of interfaces; the basic IEnumerable's enumerator would lose the Reset method and would convey no particular promise of repeatability. A new IMultiEnumerable would return an enumerator with a Reset method and and a guarantee that multiple passes would yield identical data; the enumerator might also support its own GetEnumerator method (I think that should be practical for any type which could support multi-pass enumeration; the only cost would be a 'start' pointer so the nested enumerator would be reset to the location of its original creation).
File.ReadLines() does return an
IEnumerable<T> that only works once.
No, any well behaving class that implements
IEnumerable will allow repeated enumerations.
To enumerate collections that aren't repeatable, you don't have a class that implements
IEnumerable. Instead you have a method that returns an enumerator. That way the enumerator instead of a class holds the collection, so it's not possible to call
GetEnumerator twice for the same collection. To repeat the enumerator you have to call the method to create a new collection.
An example of this is the
Enumerable.Range method. It creates the items for a range on the fly, so the range doesn't exist as a collection, which makes it non-repeatable. To enumerate the same range again you call the method to create a new range with the same bounds.