Q:

Generics, inheritance, and failed method resolution of C# compiler

I ran across a compilation issue today that baffled me.  Consider these two container classes.
public class BaseContainer<T> : IEnumerable<T>
{
    public void DoStuff(T item) { throw new NotImplementedException(); }

    public IEnumerator<T> GetEnumerator() { }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { }
}
public class Container<T> : BaseContainer<T>
{
    public void DoStuff(IEnumerable<T> collection) { }

    public void DoStuff <Tother>(IEnumerable<Tother> collection)
        where Tother: T
    {
    }
}

The former defines DoStuff(T item) and the latter overloads it with DoStuff <Tother>(IEnumerable<Tother>) specifically to get around the absence of covariance/contravariance of C# (until 4 I hear).
This code
Container<string> c = new Container<string>();
c.DoStuff("Hello World");

hits a rather strange compilation error.  Note the absence of <char> from the method call.

The type 'char' cannot be used as type parameter 'Tother' in the generic type or method 'Container.DoStuff(System.Collections.Generic.IEnumerable)'. There is no boxing conversion from 'char' to 'string'.

Essentially, the compiler is trying to jam my call to DoStuff(string) into Container.DoStuff<char>(IEnumerable<char>) because string implements IEnumerable<char>, rather than use BaseContainer.DoStuff(string).
The only way I've found to make this compile is to add DoStuff(T) to the derived class
public class Container<T> : BaseContainer<T>
{
    public new void DoStuff(T item) { base.DoStuff(item); }

    public void DoStuff(IEnumerable<T> collection) { }

    public void DoStuff <Tother>(IEnumerable<Tother> collection)
        where Tother: T
    {
    }
}

Why is the compiler trying to jam a string as IEnumerable<char> when 1) it knows it can't (given the presence of a compilation error) and 2) it has a method in the base class that compiles fine?  Am I misunderstanding something about generics or virtual method stuff in C#?  Is there another fix other than adding a new DoStuff(T item) to Container?

A:

Edit
Ok... I think I see your confusion now. You would have expected DoStuff(string) to have kept the parameter as a string and walked the BaseClass Method List first looking for a suitable signature, and failing that fallback to trying to cast the parameter to some other type.
But it happened the other way around... Instead Container.DoStuff(string) went, meh "theres a base class method there that fits the bill, but I'm going to convert to an IEnumerable and have a heart attack about what's available in the current class instead...
Hmmm... I'm sure Jon or Marc would be able to chime in at this point with the specific C# Spec paragraph covering this particular corner case
Original
Both Methods expect an IEnumerable Collection
You're passing an individual string.
The compiler is taking that string and going, 

Ok,  I have a string,  Both methods
  expect an IEnumerable<T>,  So I'll
  turn this string into an
  IEnumerable<char>... Done
Right, Check the first method...
  hmmm...  this class is a
  Container<string>  but I have an
  IEnumerable<char> so that's not right.
Check the second method, hmmm....  I
  have an IEnumerable<char> but char
  doesn't  implement string so that's
  not right either.

COMPILER ERROR
So what#s the fix, well it completely depends what your trying to achieve... both of the following would be valid, essentially, your types usage is just incorrect in your incarnation.
        Container<char> c1 = new Container<char>();
        c1.DoStuff("Hello World");

        Container<string> c2 = new Container<string>();
        c2.DoStuff(new List<string>() { "Hello", "World" });

A:

As Eric Lippert explained, the compiler chooses the DoStuff<Tother>(IEnumerable<Tother>) where Tother : T {} method because it chooses methods before checking constraints. Since string can do IEnumerable<>, the compiler matches it to that child class method.
The compiler is working correctly as described in the C# specification.
The method resolution order you desire can be forced by implementing DoStuff as an extension method.
Extension methods are checked after base class methods, so it will not try to match string against DoStuff's IEnumerable<Tother> until after it has tried to match it against DoStuff<T>.
The following code demonstrates the desired method resolution order, covariance, and inheritance. Please copy/paste it into a new project.
This biggest downside I can think of so far is that you can not use base in the overriding methods, but I think there are ways around that (ask if you are interested).
using System;
using System.Collections.Generic;

namespace MethodResolutionExploit
{
    public class BaseContainer<T> : IEnumerable<T>
    {
        public void DoStuff(T item) { Console.WriteLine("\tbase"); }
        public IEnumerator<T> GetEnumerator() { return null; }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return null; }
    }        
    public class Container<T> : BaseContainer<T> { }
    public class ContainerChild<T> : Container<T> { }
    public class ContainerChildWithOverride<T> : Container<T> { }
    public static class ContainerExtension
    {
        public static void DoStuff<T, Tother>(this Container<T> container, IEnumerable<Tother> collection) where Tother : T
        {
            Console.WriteLine("\tContainer.DoStuff<Tother>()");
        }
        public static void DoStuff<T, Tother>(this ContainerChildWithOverride<T> container, IEnumerable<Tother> collection) where Tother : T
        {
            Console.WriteLine("\tContainerChildWithOverride.DoStuff<Tother>()");
        }
    }

    class someBase { }
    class someChild : someBase { }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("BaseContainer:");
            var baseContainer = new BaseContainer<string>();
            baseContainer.DoStuff("");

            Console.WriteLine("Container:");
            var container = new Container<string>();
            container.DoStuff("");
            container.DoStuff(new List<string>());

            Console.WriteLine("ContainerChild:");
            var child = new ContainerChild<string>();
            child.DoStuff("");
            child.DoStuff(new List<string>());

            Console.WriteLine("ContainerChildWithOverride:");
            var childWithOverride = new ContainerChildWithOverride<string>();
            childWithOverride.DoStuff("");
            childWithOverride.DoStuff(new List<string>());

            //note covariance
            Console.WriteLine("Covariance Example:");
            var covariantExample = new Container<someBase>();
            var covariantParameter = new Container<someChild>();
            covariantExample.DoStuff(covariantParameter);

            // this won't work though :(
            // var covariantExample = new Container<Container<someBase>>();
            // var covariantParameter = new Container<Container<someChild>>();
            // covariantExample.DoStuff(covariantParameter);

            Console.ReadKey();
        }
    }
}

Here is the output:
BaseContainer:
        base
Container:
        base
        Container.DoStuff<Tother>()
ContainerChild:
        base
        Container.DoStuff<Tother>()
ContainerChildWithOverride:
        base
        ContainerChildWithOverride.DoStuff<Tother>()
Covariance Example:
        Container.DoStuff<Tother>()

Can you see any problems with this work around?

