Reputation: 59336
I have the following code:
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.
}
For some reason it's not able to infer the generic types for the Column
method. I need to know why. I can't give up the type inference and specify the types myself because it's just a case study for a large problem where it will be indispensable.
EDIT
I misspelled the code =/ just fixed it
Upvotes: 6
Views: 1392
Reputation: 43046
Your edited code won't compile. You can't use model
as the lambda parameter, because you already declared it as a local variable. It appears that you want to tell the compiler that the lambda parameter is a Person
by using an already-declared local of that type. But that won't work.
The correct way to inform the compiler of the type is either to declare it explicitly in the lambda as others have said:
var b = CardView.Column((Person m) => m.Name);
or to supply type arguments to the generic method:
var b = CardView.Column<Person, string>(m => m.Name);
Upvotes: 0
Reputation: 437336
The technical answer would be "because the specification doesn't say you can do that". Quoting the spec, section 7.5.2 (type inference):
7.5.2.1 The first phase
For each of the method arguments Ei:
- If Ei is an anonymous function, an explicit parameter type inference (§7.5.2.7) is made from Ei to Ti
- Otherwise, if Ei has a type U and xi is a value parameter then a lower-bound inference is made from U to Ti.
- Otherwise, if Ei has a type U and xi is a ref or out parameter then an exact inference is made from U to Ti.
- Otherwise, no inference is made for this argument.
and:
7.5.2.7 Explicit parameter type inferences
An explicit parameter type inference is made from an expression E to a type T in the following way:
- If E is an explicitly typed anonymous function with parameter types U1…Uk and T is a delegate type or expression tree type with parameter types V1…Vk then for each Ui an exact inference (§7.5.2.8) is made from Ui to the corresponding Vi.
Since the anonymous function in your example is not explicitly typed, no inference can be made. This also tells us that to have the inference made, you can help by specifying the type of the function:
var b = CardView.Column((Person m) => m.Name);
Now this is explicitly a Func<Person, string>
, so inference is successful.
Upvotes: 2
Reputation: 28608
There is no TModel
argument (or a generic type that uses TModel
) in that method signature, so the compiler doesn't know the type of m
.
Upvotes: 1
Reputation: 754585
In order for the compiler to perform type inference it has to be given some sort of type information. In this scenario the only information it's provided is an untyped lambda expression. The compiler really has nothing to go on here.
There are a couple of ways to resolve this. The easiest is to add a type to the lambda paramater
var b = CardView.Column((Person m) => m.Name);
Upvotes: 7