Infer parameter type of object passed as generic parameter for source argument in extension method

Topics: C# Language Design, General
Apr 13, 2014 at 1:07 PM
Consider an extension method with generic parameters like this:
public static class Mapper
{
    public static TTarget Map<TSource, TTarget>(this TSource source, Func<TSource, TTarget> func)
    {
        return func(source);
    }
}
With this ideal usage:
Foo2 obj = new Foo1().Map<Foo2>(f => { return ... ; });
This doesn't work however. You have to explicitly specifiy all type arguments, even TSource.

It would be much simpler to infer that type parameter and not having to specify TSource.
Apr 13, 2014 at 2:18 PM
Edited Apr 13, 2014 at 2:18 PM
Why do you need to specify the Foo2 argument at all? Just write:
Foo2 obj = new Foo1().Map(f => new Foo2());
Apr 13, 2014 at 3:34 PM
Edited Apr 13, 2014 at 3:35 PM
mdanes wrote:
Why do you need to specify the Foo2 argument at all? Just write:
Foo2 obj = new Foo1().Map(f => new Foo2());
To clarify my concern:

Consider the case when not taking the last argument (like the Func<TSource, TTarget>) and/or that the method is not returning a value from which to infer the type for TTarget. The TSource (or T1) becomes superfluous here:
new Foo1().DoSomething<Foo2>();
The extension method:
public static void DoSomething<T1, T2>(this T1 source)
{
    // Do something.
}
Apr 14, 2014 at 10:17 AM
I see. Well, the problem with this is that currently you can have both DoSomething<T> and DoSomething<T1, T2> and it's possible to write new Foo1().DoSomething<Foo1>(), that will call the DoSomething<T>. new Foo1().DoSomething<Foo2> is invalid now but to make it valid you'd have to add some kind of overload resolution for generic arguments. That's non trivial and it may break existing code.

It's also worth noting that generic methods with type arguments that cannot be inferred from the usage aren't recommended. They tend to make the code less easier to read.