在这个问题中,当提到编译器时,我实际上指的是 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
当我用鼠标悬停在扩展方法上时,我收到此错误消息(我已将<
和>
个字符替换为{{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.B
是T1
,因此您可以在智能感知的帮助下用表达最后一个参数。
答案 0 :(得分:4)
如果我理解正确的话, VS2013 中的所有内容都按预期运行:
你的第一个案例:
你的第二个案例:
我开始输入l.
并且IntelliSense向我显示l
具有可以使用的属性B
。所以,如果我是正确的,并且在 VS2013 中正确推断,而在 VS2015 >> 强>,那肯定是 VS2015 IntelliSense中可以向微软报告的错误。
答案 1 :(得分:2)
我发现你的问题很有趣,因为我使用VS 2015,我想我也可以尝试一下。我得到了和你一样的错误,所以我猜它可能是一个VS bug,因为在其他版本中它运行正常。
这是我的错误:
我还在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修复它......