2014-02-26 46 views
4

问这个最简单的方法是要表明,在手演示问题的例子(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,但它为什么以这种方式实现?任何人都可以指出我对此行为的理由或规范吗?

回答

4

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

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

这是在规范中的§7.4指定:

在类型T具有K个类型的参数的名称N的成员查找的处理过程如下:

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

    • 如果T是一个类型参数,则该组是集合中的每个类型的名为N可访问成员的并集s被指定为T的主要约束或次要约束(§10.1.5),以及对象中名为N的可访问成员集合。
+0

_ “名为N对象” _ - 什么对象? –

+0

@RoyiNamir:类型'System.Object'。 – SLaks