为什么不能推断出这些泛型类型?

本文关键字:泛型类型 不能 推断出 为什么 | 更新日期: 2023-09-27 18:17:20

我有以下代码:

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方法的泛型类型。我要知道原因。我不能放弃类型推断而自己指定类型,因为这只是一个大问题的案例研究,在这个问题中它是必不可少的。

编辑

我拼错了代码=/只是修复它

为什么不能推断出这些泛型类型?

为了让编译器执行类型推断,必须给它某种类型信息。在这个场景中,它提供的唯一信息是一个未类型化的lambda表达式。编译器在这里没有什么可做的。

有几种方法可以解决这个问题。最简单的方法是向lambda参数

添加类型
var b = CardView.Column((Person m) => m.Name);

技术上的答案是"因为规范没有说你可以这样做"。引用规范第7.5.2节(类型推断):

7.5.2.1第一阶段

对于每个方法参数Ei:

  1. 如果Ei是一个匿名函数,一个显式的参数类型推断(§7.5.2.7)由Ei制成Ti
  2. 否则,如果Ei有类型U和xi是一个值参数,那么从U到Ti。
  3. 如果Ei类型为U,且xi为ref/out形参然后从U到Ti得到一个精确的推断。
  4. 否则,对该参数不做任何推断。

:

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>,所以推理是成功的。

在该方法签名中没有TModel参数(或使用TModel的泛型类型),因此编译器不知道m的类型

您编辑的代码无法编译。不能使用model作为lambda参数,因为已经将其声明为局部变量。您似乎希望通过使用已经声明的该类型的局部变量来告诉编译器lambda参数是Person。但这行不通。

告知编译器该类型的正确方法是在lambda中显式声明它,就像其他人所说的:

var b = CardView.Column((Person m) => m.Name); 

或为泛型方法提供类型参数:

var b = CardView.Column<Person, string>(m => m.Name);