无法从使用

时间:2016-07-13 10:45:56

标签: c# .net generics visual-studio-2015 roslyn

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

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

编译器 NOT 能够在输入时推断出T1

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

此屏幕截图示例将更详细地介绍无法推断的含义
enter image description here

当我用鼠标悬停在扩展方法上时,我收到此错误消息(我已将<>个字符替换为{{1} }和[,因为StackOverflow无法格式化引用中的那些:

  

方法&#39; FooBar [T1,T2]的类型参数(此助手[IEnumerable [T1]],表达式[Func [T1,IEnumerable [T2]]]&#39;无法推断   从用法。尝试明确指定类型参数。

但是在完成手动这样的时候:

]

编译器很高兴。

为什么编译器/ IntelliSense(或Visual Studio 的自动完成功能)无法找出helper.FooBar(l => l.B, l => l.C); //compiler infers that T1 is A, T2 is B and T3 is C 并希望我在开始输入时明确指定类型参数?

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

3 个答案:

答案 0 :(得分:4)

如果我理解正确的话, VS2013 中的所有内容都按预期运行:

你的第一个案例:

你的第二个案例:

我开始输入l.并且IntelliSense向我显示l具有可以使用的属性B。所以,如果我是正确的,并且 VS2013 中正确推断,而 VS2015 > 强>,那肯定是 VS2015 IntelliSense中可以向微软报告的错误。

答案 1 :(得分:2)

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

这是我的错误:

enter image description here

我还在CTRL + SPACE上获得了没有建议

修改

可以看到类似的错误here

所以,因为在VS的旧版本中,这是有效的,所以这就是为什么它可以被认为是一个bug。

答案 2 :(得分:2)

正如我所说,我有same problem.(而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修复它......