In the October tech preview of Visual C#, there was an interesting change to the definition of Systems.Collections.Generic.IEnumerable<T> -- the generic interface for enumeration. Now, it inherits from the non-generic interface, System.Collections.IEnumerable. A similar change was made to System.Collections.Generic.IEnumerator<T> -- it now inherits the non-generic System.Collections.IEnumerator.

Curiously, however, the other collection interfaces (most notably ICollection<T>, IList<T>), do not exhibit such inheritance of non-generic interfaces. I've thought about this for a while, and I don't really understand why this was done.

If you are writing a class that implements IEnumerable<T>, you now always have to implement two different GetEnumerators:

class X: IEnumerable<T> {
    public IEnumerator<T> GetEnumerator() {
        /* blah, blah, blah */
    }

    IEnumerator IEnumerable.GetEnumerator() {
       return GetEnumerator();
    }
}

Somewhat irritatingly, the implementation of IEnumerable.GetEnumerator is completely boilerplate, but you still have to write it. Shouldn't the compiler be able to do that automatically?

Once you've written such a class, it iteroperates somewhat better with non-generic code that uses the non-generic IEnumerable. But that could just as easily be accomplished by having X explicitly inherit both IEnumerable<T> and IEnumerable -- in fact List<T> already did that before this change came along. So I don't see any real advantage there.

I suspect the real motivation came from the common language specification (CLS). Suppose that (ignoring that it already exists), you were developing a class DirectoryInfo that gives information about a file system directory. You probably would have to have methods that return the files and sub-directories, say:

    IEnumerable<DirectoryInfo> GetSubdirectories()
    IEnumerable<FileInfo> GetFiles()

Unfortunately, IEnumerable is not a CLS-compliant type. If you wanted DirectoryInfo to be CLS-compliant, you would have to provide non-generic equivalents, with different names:

    IEnumerable GetSubdirectoriesNongeneric()
    IEnumerable GetFilesNongeneric()

Clearly those names aren't palatable! But there really isn't a way to provide two good names for the same functionality. Possibly the intent of the change in inheritance relationship is to allow IEnumerable<T> to be a CLS-compliant type, and to require non-generic languages to interpret the generic IEnumerable<T> as the non-generic IEnumerable. So this might be a way to push just a little tiny bit of generics into the CLS, so that class authors can return IEnumerable and still be CLS compliant.

However, I haven't seen any such change in CLS-compliance status of generics published anywhere. So this is just speculation. Even if this is the reason, it bothers me somewhat. Why IEnumerable<T> but not ICollection<T>? This trick only works with return types; are we supposed to use overloading in cases where IEnumerable<T> is passed in? Isn't this permanently making the definition of IEnumerable<T> strange and inconvenient, just because generics isn't CLS compliant yet? Frankly, it feels like a kludge.

I'm hoping that the BCL Team, Krzysztof Cwalina, or Brad Abrams might be able to shed more light about this in their blogs.