InBetween InBetween - 2 months ago 8
C# Question

Why does the compiler not infer the generic type

I have the following method:

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


And I want to call it the following way:

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


Why can't the compiler figure out
s
is
string
and therefore
T
is
string
? What rule in the spec makes the inference algorithm fail here?

Answer

I admit I haven't checked the entire C# 5.0 specification, but section 8.5.1 Local variable declarations talks a bit about the var keyword, which is used to declare an inferred type.

Here are the rules for variables declared for var and for all inferred variables:

  • The local-variable-declaration cannot include multiple local-variable-declarators.
  • The local-variable-declarator must include a local-variable-initializer.
  • The local-variable-initializer must be an expression.
  • The initializer expression must have a compile-time type.
  • The initializer expression cannot refer to the declared variable itself

Because this is a lambda, your inferred initializer is:

string.IsNullOrEmpty(s)

OK, so...

  • It doesn't have multiple local-variable-declarators. Pass.
  • It includes a local-variable-intitalizer because it's a lambda. Pass.
  • It's an expression. Pass.
  • string.IsNullOrEmpty returns a string. Pass.
  • It relies on itself being passed to a function to determine the type. Fail.

So, to answer your question, your initializer ultimately fails because its type must be known before you can pass it to a method.

Lambdas can fix this relatively easily, though:

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