Why doesn't C# support implied generic types on class constructors?

Actually, your question isn't bad. I've been toying with a generic programming language for last few years and although I've never come around to actually develop it (and probably never will), I've thought a lot about generic type inference and one of my top priorities has always been to allow the construction of classes without having to specify the generic type.

C# simply lacks the set of rules to make this possible. I think the developers never saw the neccesity to include this. Actually, the following code would be very near to your proposition and solve the problem. All C# needs is an added syntax support.

class Foo<T> {
    public Foo(T x) { … }
}

// Notice: non-generic class overload. Possible in C#!
class Foo {
    public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); }
}

var x = Foo.ctor(42);

Since this code actually works, we've shown that the problem is not one of semantics but simply one of lacking support. I guess I have to take back my previous posting. ;-)


Why doesn't C# support this class level generic type inference?

Because they're generally ambiguous. By contrast, type inference is trivial for function calls (if all types appear in arguments). But in the case of constructor calls (glorified functions, for the sake of discussion), the compiler has to resolve multiple levels at the same time. One level is the class level and the other is the constructor arguments level. I believe solving this is algorithmically non-trivial. Intuitively, I'd say it's even NP-complete.

To illustrate an extreme case where resolution is impossible, imagine the following class and tell me what the compiler should do:

class Foo<T> {
    public Foo<U>(U x) { }
}

var x = new Foo(1);

Thanks Konrad, that's a good response (+1), but just to expand on it.

Let's pretend that C# has an explicit constructor function:

//your example
var x = new Foo( 1 );

//becomes
var x = Foo.ctor( 1 );

//your problem is valid because this would be
var x = Foo<T>.ctor<int>( 1 );
//and T can't be inferred

You're quite right that the first constructor can't be inferred.

Now let's go back to the class

class Foo<T> 
{
    //<T> can't mean anything else in this context
    public Foo(T x) { }
}

//this would now throw an exception unless the
//typeparam matches the parameter
var x = Foo<int>.ctor( 1 );

//so why wouldn't this work?
var x = Foo.ctor( 1 );

Of course, if I add your constructor back in (with its alternate type) we have an ambiguous call - exactly as if a normal method overload couldn't be resolved.