Your question was hotly debated when C# 2.0 and the generic type system in the CLR were being designed. So hotly, in fact, that the "bound" C# 2.0 specification published by A-W actually has the wrong rule in it! There are four possibilities:
1) Make it illegal to declare a generic class that could POSSIBLY be ambiguous under SOME construction. (This is what the bound spec incorrectly says is the rule.) So your Foo<T>
declaration would be illegal.
2) Make it illegal to construct a generic class in a manner which creates an ambiguity. declaring Foo<T>
would be legal, constructing Foo<double>
would be legal, but constructing Foo<int>
would be illegal.
3) Make it all legal and use overload resolution tricks to work out whether the generic or nongeneric version is better. (This is what C# actually does.)
4) Do something else I haven't thought of.
Rule #1 is a bad idea because it makes some very common and harmless scenarios impossible. Consider for example:
class C<T>
{
public C(T t) { ... } // construct a C that wraps a T
public C(Stream state) { ... } // construct a C based on some serialized state from disk
}
You want that to be illegal just because C<Stream>
is ambiguous? Yuck. Rule #1 is a bad idea, so we scrapped it.
Unfortunately, it is not as simple as that. IIRC the CLI rules say that an implementation is allowed to reject as illegal constructions that actually do cause signature ambiguities. That is, the CLI rules are something like Rule #2, whereas C# actually implements Rule #3. Which means that there could in theory be legal C# programs that translate into illegal code, which is deeply unfortunate.
For some more thoughts on how these sorts of ambiguities make our lives wretched, here are a couple of articles I wrote on the subject:
http://blogs.msdn.com/ericlippert/archive/2006/04/05/569085.aspx
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx