为什么编译器不推断泛型类型

时间:2016-09-24 23:09:12

标签: c# generics visual-studio-2015 language-lawyer type-inference

我有以下方法:

public static void Foo<T>(Predicate<T> validator) { ... }

我想用以下方式来称呼它:

Foo(s => string.IsNullOrEmpty(s));

为什么编译器确定sstring,因此Tstring?规范中的哪条规则会使推理算法失败?

1 个答案:

答案 0 :(得分:1)

我承认我还没有检查过整个C#5.0规范,但 8.5.1局部变量声明部分讨论了var关键字,用于声明推断类型。

以下是为var和所有推断变量声明的变量的规则:

  • local-variable-declaration不能包含多个local-variable-declarators。
  • local-variable-declarator必须包含local-variable-initializer。
  • local-variable-initializer必须是表达式。
  • 初始化程序表达式必须具有编译时类型。
  • 初始化程序表达式不能引用声明的变量本身

因为这是一个lambda,你推断的初始化器是:

string.IsNullOrEmpty(s)

好的,所以...

  • 它没有多个局部变量声明符。通过。
  • 它包含 local-variable-intitalizer ,因为它是一个lambda。通过。
  • 这是一个表达。通过。
  • string.IsNullOrEmpty返回一个字符串。通过。
  • 它依赖于将自身传递给函数来确定类型。失败。

因此,要回答您的问题,您的初始化程序最终会失败,因为在将其传递给方法之前必须知道其类型。

Lambda可以相对容易地解决这个问题,但是:

Foo(string s => string.IsNullOrEmpty(s));