Matias Cicero Matias Cicero - 1 month ago 6
C# Question

Is type inference done from right to left?

Consider the following example:

public class Person
{
public int Age { get; set; }
}

public class Builder<TSource>
{
public Builder<TSource> WithValue<TValue>(Func<TSource, TValue>, TValue value)
{
// ...
}
}


These two lines work and run just fine:

Builder<Person> builder = new Builder<Person>();
builder.WithValue(p => p.Age, 20);


But so do these:

Builder<Person> builder = new Builder<Person>();
object age = "20"; // <-- string value
builder.WithValue(p => p.Age, age);


Type inference is not working the way I expect it to work on the latter example.

If I specify an expression
p => p.Age
, which is
Func<Person, int>
, I expect the second argument to be constrained to an
int
type. Yet, I am able to pass an
object
just fine.

I'm guessing this is because type inference is being done from right to left. That is,
TValue
argument is being infered as an
object
and then my
Func<TSource, TValue>
expression is constrained to a
Func<Person, object>
, which
p => p.Age
satisfies just fine.

Is my assumption correct?

If so, why is type inference being done this way? I find it more natural from left to right.

Answer

It's not order dependant at all. The parameter p => p.Age is adding the constraint that whatever TValue is must be a type that can store an int. That could be int or any type it inherits from, such as, say, object. When you pass in age you're saying that TValue must be a type that can store an object. It will then choose the most derived type that meets all of those constraints, which in this case, is object. The same thing would happen if you changed the order of the parameters.