【问题标题】:Is type inference done from right to left?类型推断是从右到左进行的吗?
【发布时间】:2016-10-31 13:47:59
【问题描述】:

考虑以下示例:

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 =&gt; p.Age,即Func&lt;Person, int&gt;,我希望第二个参数被限制为int 类型。然而,我可以通过object 就好了。

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

我的假设正确吗?

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

【问题讨论】:

    标签: c# .net generics type-inference


    【解决方案1】:

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

    【讨论】:

    • 不是派生最多的类型int吗?
    • @MatiasCicero 类型int 不满足这两个约束;它只满足两个约束之一,因为您不能将object 存储在int 类型的变量中。
    • 我想我现在明白了。感谢您的快速回答!
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多