Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the C# compiler unable to infer method type parameters by expected return type?

This seems odd to me, but I remember a thread where Eric Lippert commented on the inability (by design, or at least convention, I think) of C# to overload methods based on return type, so perhaps it's in some convoluted way related to that.

Is there any reason this does not work:

public static T Test<T>() where T : new()
{
    return new T();
}

// Elsewhere
SomeObject myObj = Test();

But this does:

 var myObj = Test<SomeObject>();

From a certain perspective, they're both fine, in that you're not Repeating Yourself (in a very small way), but is this just a different pass of the compiler?

like image 939
Marc Bollinger Avatar asked Jan 12 '11 02:01

Marc Bollinger


2 Answers

First off, this is "overloading based on return type":

void M(int x){...}
int M(int x){...}
string M(int x){...}

The declarations are not legal; you can't overload a method based on return type because the return type is not part of the signature, and the signature has to be unique.

What you are talking about is method type inference based on the method's return type. We don't support that either.

The reason is because the return type might be what you are trying to figure out.

M(Test());

What's the return type of Test? That depends on which overload of M we choose. What overload of M do we choose? That depends on the return type of Test.

In general, C# is designed so that every subexpression has a type, and the types are worked out from the "inside" towards the "outside", not from the outside to the inside.

The notable exceptions are anonymous functions, method groups, and null:

M(x=>x+1)

What's the type of x=>x+1? It depends on which overload of M is called.

M(N); // N is a method group

what's the type of N? Again, it depends on which overload of M is called.

And so on. In these cases we do reason from "outside" to "inside".

Type inference involving lambdas is extremely complicated and was difficult to implement. We don't want to have that same complication and difficulty throughout the compiler.

like image 53
Eric Lippert Avatar answered Oct 06 '22 00:10

Eric Lippert


Except for typeless expressions (null, method groups, and lambda expressions), the type of an expression must be statically determinable by the expression itself, regardless of context.

In other words, the type of an expression Test() cannot depend on what you're assigning it to.

like image 22
SLaks Avatar answered Oct 05 '22 22:10

SLaks