无法从用法中推断出开放泛型类型参数

Open generic type arguments cannot be inferred from the usage

在这个问题中,当提到编译器时,我实际上指的是Roslyn编译器。使用IntelliSense时出现问题,推测是同一个编译器

出于演示目的和完整性,使用了以下 类(使用 Visual Studio 2015 with C# 6.0 和 .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> { }

看下面的扩展方法:

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

编译器能够在像这样消费时推断它:

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

还要看这个重载的扩展方法:

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

编译器无法在输入时推断出T1

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

这个截图示例将更多地描述我的意思 无法推断:

此外,当我将鼠标悬停在扩展方法上时,我收到此错误消息(我已将 <> 字符替换为 [],因为 Whosebug 无法格式化引号中的那些 ):

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.

但是当像这样手动完成它时:

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

编译器很高兴。

为什么 compiler/IntelliSense( 或 Visual Studio 的自动完成功能)无法找出 T1 并希望我指定当我开始输入时明确输入参数?

注意 如果我在我的示例中到处省略 IEnumerable<>,编译器可以在键入时愉快地推断出所有内容。
在您手动输入 l => l.B 后,编译器也会很高兴。然后它知道 T1A,因此您可以在 IntelliSense 的帮助下用 表达最后一个参数

如果我没理解错的话,在 VS2013:

中一切都按预期工作

您的第一个案例:

你的第二个案例:

我开始输入 l.,IntelliSense 显示 l 有一个 属性 B 可以使用。因此,如果我是对的,它 VS2013 正确推断 而它 VS2015,那肯定是VS2015 IntelliSense 的bug,可以反馈给微软

我发现你的问题很有趣,因为我使用的是 VS 2015,所以我想我也可以试试。我得到了和你一样的错误,所以我猜它可能是一个 VS 错误,因为在其他版本中它工作正常。

这是我的错误:

而且我在 CTRL + SPACE 上也得到 没有建议

编辑:

可以看到类似的错误

所以,既然在旧版本的 VS 中这是有效的,那么这就是为什么它可以被认为是一个错误的原因。

正如我所说,我有 (And here 是错误报告)
它与表达式或 IEnumerable 无关。
这是一个简化的例子

using System;

namespace ConsoleApplicationExpressionTree
{

    public static class Extentions
    {
        static void Main() { }
        static void AMethod(string[] args)
        {
            SetValue(new Customer(), e => e.Name   /*type here */, "TheName");

        }

        public static void SetValue<TEntity, TProperty>(TEntity instance, Func<TEntity, TProperty> expression, TProperty newValue)
        {

        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

我刚刚注意到,如果您从方法中删除第三个参数,它就会起作用!!!

using System;

namespace ConsoleApplicationExpressionTree
{

    public static class Extentions
    {
        static void Main() { }
        static void AMethod(string[] args)
        {
            SetValue(new Customer(), e => e.Name   /*type here */);

        }

        public static void SetValue<TEntity, TProperty>(TEntity instance, Func<TEntity, TProperty> expression)
        {

        }
    }
    public class Customer
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

因此,如果您非常幸运,您也许可以通过调整参数来修复当前示例。
不行就等MS修复吧...