类型推断是从右到左进行的吗?

Is type inference done from right to left?

考虑以下示例:

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

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

这两行工作 运行 很好:

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

但这些也是如此:

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

类型推断在后一个示例中的工作方式与我期望的不同。

如果我指定表达式 p => p.Age,即 Func<Person, int>,我希望第二个参数被限制为 int 类型。然而,我能够通过 object 就好了。

我猜这是因为类型推断是从右到左进行的。也就是说,TValue 参数被推断为 object,然后我的 Func<TSource, TValue> 表达式被限制为 Func<Person, object>p => p.Age 正好满足。

我的假设正确吗?

如果是这样,为什么要这样进行类型推断?我觉得从左到右更自然。

它完全不依赖于顺序。参数 p => p.Age 添加了约束,即无论 TValue 是什么,都必须是可以存储 int 的类型。这可能是 int 或它继承自的任何类型,例如 object。当您传入 age 时,您是在说 TValue 必须是可以存储 object 的类型。然后它将选择满足所有这些约束的最派生类型,在本例中为 object。如果您更改参数的顺序,也会发生同样的事情。

既不是从左到右,也不是从右到左。类型推断采用给定情况下可用的类型信息,并尝试找出可以替换的类型,以便它与所有相应的表达式兼容。这通常由最近的共同祖先满足。在您的情况下, intobject 都将 object 作为最近的共同祖先。但是,一般来说,由于接口的原因,分辨率可能会稍微复杂一些。