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

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代码中可以看出,GetProp<T>的通用版本在IFace类型上使用了ldtoken,但为什么要以这种方式实现呢?有人能指向这种行为的理由或规范吗?
1个回答

4

由于成员查找是在编译时完成的。

因此编译器会将你的lambda表达式中的x.A绑定到接口中A属性。

这在规范的§7.4中有说明:

对于类型T中具有K个类型参数名称为N的成员查找处理如下:

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

    • 如果T是类型参数,则集合是:将每个指定为T的主要约束或次要约束(§10.1.5)的类型中名为N的可访问成员集合取并集,再加上object中名为N的可访问成员集合。

“在对象中命名为N” - 什么对象? - Royi Namir
@RoyiNamir:类型为 System.Object - SLaks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接