为什么泛型类型的表达式引用约束类型而不是运行时类型?

时间:2014-02-26 20:25:46

标签: c# generics linq-expressions

最简单的方法是展示演示手头问题的示例(LinqPad)代码:

void Main()
{
    GetProp<IFace>().DeclaringType.Dump(); // iface
    GetProp<C>().DeclaringType.Dump(); // iface
    GetProp().DeclaringType.Dump(); // c
}

public interface IFace { int A { get; set; } }

public class C : IFace { public int A { get; set; } }

public PropertyInfo GetProp<T>() where T : IFace
{
    return ExtractProperty((T x) => x.A);
}

public PropertyInfo GetProp()
{
    return ExtractProperty((C x) => x.A);
}

private PropertyInfo ExtractProperty<T, V>(Expression<Func<T, V>> exp)
{
    return (PropertyInfo) ((MemberExpression) exp.Body).Member;
}

我很感兴趣GetProp<C>使用的原因是IFace上的属性而不是C上的属性。谁能解释这种行为?查看IL code,我可以看到GetProp<T>的通用版本在IFace类型上使用ldtoken,但为什么会以这种方式实现?任何人都可以指出这种行为的理由或规范吗?

1 个答案:

答案 0 :(得分:4)

因为成员查找是在编译时完成的。

编译器将lambda中的x.A绑定到接口中的A属性。

这在规范§7.4中规定:

  

在类型T中使用K类型参数的名称N的成员查找按如下方式处理:

     
      
  • 首先,确定一组名为N的可访问成员:

         
        
    • 如果T是类型参数,则该集合是指定为T的主要约束或次要约束(第10.1.5节)的每种类型中名为N的可访问成员集合以及集合对象中名为N的可访问成员。
    •   
  •