我有以下代码:
public static class CardView {
public static object Column<TModel, TResult>(Func<TModel, TResult> field) {
return null;
}
}
public class Person
{
public string Name { get; set; }
public bool Gender { get; set; }
}
void Main()
{
var model = new Person() { Name = "Andre", Gender = true };
var b = CardView.Column(model => model.Name); // ERROR
// The type arguments for method 'UserQuery.CardView.Column<TModel,TResult>(System.Func<TModel,TResult>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
}
由于某种原因,它无法推断Column
方法的泛型类型。我需要知道原因。我不能放弃类型推断并自己指定类型,因为它只是一个大问题的案例研究,它将是不可或缺的。
修改
我拼错了代码= /刚刚修好了
答案 0 :(得分:7)
为了让编译器执行类型推断,必须给它一些类型信息。在这种情况下,它提供的唯一信息是无类型的lambda表达式。编译器真的没有什么可以继续下去的。
有几种方法可以解决这个问题。最简单的方法是向lambda参数添加一个类型
var b = CardView.Column((Person m) => m.Name);
答案 1 :(得分:2)
技术答案是“因为规范并没有说你能做到”。引用the spec,第7.5.2节(类型推断):
7.5.2.1第一阶段
对于每个方法参数Ei:
- 如果Ei是匿名函数,则是显式参数类型推断 (§7.5.2.7)由Ei制成Ti
- 否则,如果Ei的类型为U和xi 是一个值参数,然后从U到下限推断 的Ti。
- 否则,如果Ei具有类型U并且xi是ref或out参数 然后从U到Ti进行精确推断。
- 否则,不会对此参数进行推断。
醇>
和
7.5.2.7显式参数类型推断
在下面,从表达式E到类型T进行显式参数类型推断 方式:
- 如果E是显式类型的匿名函数,参数类型为U1 ... Uk和T是带参数的委托类型或表达式树类型 类型V1 ... Vk然后为每个Ui进行精确推理(第7.5.2.8节) 从Ui到相应的Vi。
由于示例中的匿名函数未显式输入,因此无法进行推理。这也告诉我们,要进行推理,您可以通过指定函数的类型来帮助:
var b = CardView.Column((Person m) => m.Name);
现在这显然是Func<Person, string>
,因此推断是成功的。
答案 2 :(得分:1)
在该方法签名中没有TModel
参数(或使用TModel
的泛型类型),因此编译器不知道m
的类型。
答案 3 :(得分:0)
您编辑的代码无法编译。您不能将model
用作lambda参数,因为您已将其声明为局部变量。看来你想通过使用已经声明的那种类型的本地来告诉编译器lambda参数是Person
。但那不行。
通知编译器类型的正确方法是在lambda中显式声明它,正如其他人所说:
var b = CardView.Column((Person m) => m.Name);
或为泛型方法提供类型参数:
var b = CardView.Column<Person, string>(m => m.Name);