Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open generic type arguments cannot be inferred from the usage

In this question, when mentioning the compiler, I'm actually referring to the Roslyn compiler. The problem arises when using IntelliSense, which is presumed to be the same compiler.

For demonstration purposes and completeness, the following classes are used (using Visual Studio 2015 with C# 6.0 and .NET 4.6.1):

public class A
{
    public IEnumerable<B> B { get; set; }
}
public class B
{
    public IEnumerable<C> C { get; set; }
}
public class C { }
public class Helper<T> { }

Behold the following extension method:

public static void FooBar<T1, T2>(
    this Helper<IEnumerable<T1>> helper,
    Expression<Func<T1, IEnumerable<T2>>> expression) { ... }

The compiler is able to infer it while consuming like this:

Helper<IEnumerable<B>> helper = ...;
helper.FooBar(l => l.C); //T1 is B and T2 is C

Also behold this overloaded extension method:

public static void FooBar<T1, T2, T3>(
    this Helper<T1> helper,
    Expression<Func<T1, IEnumerable<T2>>> expression1,
    Expression<Func<T2, IEnumerable<T3>>> expression2) { ... }

The compiler is NOT able to infer T1 when typing it like this:

Helper<A> helper = ...;
helper.FooBar(l => l. //compiler/IntelliSense cannot infer that T1 is A

This screenshot example will describe more of what I mean with not able to infer:
enter image description here

Also I'm getting this error message when hovering over the extension method with my mouse (I've replaced the < and > characters with [ and ] respectively, because StackOverflow cannot format those in a quote):

The type arguments for method 'FooBar[T1,T2](this Helper[IEnumerable[T1]], Expression[Func[T1, IEnumerable[T2]]])' cannot be inferred from the usage. Try specifying the type arguments explicitly.

But when completing it manually like this:

helper.FooBar(l => l.B, l => l.C); //compiler infers that T1 is A, T2 is B and T3 is C

the compiler is happy.

Why can't the compiler/IntelliSense (or the autocomplete feature of Visual Studio) figure out T1 and wants me to specify the type arguments explicitly when I start typing?

Note that if I omit IEnumerable<> everywhere in my examples, the compiler can happily infer everything while typing.
The compiler is also happy after you manually type in l => l.B. It then knows T1 is A, so you can express the last argument with the help of IntelliSense.

like image 402
QuantumHive Avatar asked Jul 13 '16 10:07

QuantumHive


1 Answers

If I understood you correctly, everything is working as expected for me in VS2013:

Your first case:

Your second case:

I'm starting to type the l. and IntelliSense shows me that l has a property B that can be used. So if I'm right and it infers correctly in VS2013 whereas it doesn't infer in VS2015, then it's definitely a bug in VS2015 IntelliSense that can be reported to Microsoft.

like image 106
Ivan Yurchenko Avatar answered Oct 07 '22 18:10

Ivan Yurchenko