Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Why doesn't generic type inference work when there are multiple type arguments?

Tags:

c#

generics

Here are two samples:

This works fine:

void Main()
{
    var list = Queryable.ProjectTo(typeof(Projection));
}

public static class QueryableExtensions
{
    public static ProjectionList<T> ProjectTo<T>(this IQueryable<T> queryable, Type projectionType)
    {
        return new ProjectionList<T>(queryable, projectionType);
    }
}

This throws the following error:

Using the generic method 'QueryableExtensions.ProjectTo(System.Linq.IQueryable)' requires 2 type arguments

void Main()
{
    var list = Queryable.ProjectTo<Projection>();
}

public static class QueryableExtensions
{
    public static ProjectionList<T, P> ProjectTo<T, P>(this IQueryable<T> queryable)
    {
        return new ProjectionList<T, P>(queryable);
    }
}

Of course the first example requires 1 type argument, however the compiler can figure out what it is so I don't need to supply any. The second example requires 2 type arguments but the compiler knows what T is so why does it not only require the one that cannot be inferred?

For the record I am using the first example just fine in my code, but I like the syntax of the second much better and there may be a case where I would like to have the generic type of the projection. Is there any way to achieve this or am I barking up the wrong tree?

Thanks!

like image 594
Jeff Camera Avatar asked Jan 17 '23 10:01

Jeff Camera


2 Answers

The issue is not the 2 parameters, but rather: from where would it infer it? Generic parameter inference only looks at parameters, and specifically does not consider return types. There is nothing in the parameters that would suggest P. It is required that either generic type inference provides all of them, or all of them are specified explicitly. Interestingly, there was once mention of "mumble-typing" which, as I interpret it (since it never got defined fully) would have allowed you to mix and match, like you want. Imagine:

blah.ProjectTo<?,SomeType>();

(the exact syntax doesn't matter since this language feature doesn't exist) - but it would mean "there are 2 genericmtype arguments; you (the compiler) figure out the first parameter; the second is SomeType".

like image 125
Marc Gravell Avatar answered Jan 30 '23 08:01

Marc Gravell


That's because generic parameter inference works only with input parameters. In your second example the P parameter appears only at the return type, thus the inference cannot work. So when you write:

var list = Queryable.ProjectTo<Projection>();

T is Projection but what's P for you?

But even if you write:

ProjectionList<Projection, FooBar> list = Queryable.ProjectTo();

it still wouldn't work.

like image 28
Darin Dimitrov Avatar answered Jan 30 '23 07:01

Darin Dimitrov