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

时间:2016-10-31 13:48:00

标签: c# .net generics type-inference

考虑以下示例:

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满足要求。

我的假设是否正确?

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

2 个答案:

答案 0 :(得分:5)

根本不依赖于订单。参数TValue正在添加约束,即int必须是可以存储int的类型。这可以是object或其继承的任何类型,例如age。当您传递TValue时,您说object必须是可以存储object的类型。然后,它将选择满足所有这些约束的派生类型,在本例中为{{1}}。如果你改变了参数的顺序,就会发生同样的事情。

答案 1 :(得分:1)

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