【问题标题】:How to tell if MemberInfo represents an override如何判断 MemberInfo 是否代表覆盖
【发布时间】:2013-07-13 04:58:54
【问题描述】:

给定以下代码:

public class Base {
    public virtual void Method() { }
}

public class Derived : Base {
    public override void Method() { }
}

...

var baseMethodInfo = typeof(Base).GetMember("Method")[0];
var derivedMethodInfo = typeof(Derived).GetMember("Method")[0];

是否可以确定派生方法信息是否表示覆盖基类中另一个的方法声明?

another question 中,观察到如果Method 在基类中被声明为抽象(并且未实现),那么derivedMethodInfo.DeclaringType 将出现为Base,这在阅读@EricLippert 的cmets 之后是有意义的。我注意到在本示例中,由于派生类重新声明了该方法,即derivedMethodInfo.DeclaringType == derivedMethodInfo.ReflectedType,即。派生的。

baseMethodInfo 和 derivedMethodInfo 之间似乎没有任何联系,除了它们的名称相同并且它们各自的声明类型出现在同一个继承链中。有没有更好的连接方式?

我问的原因是,似乎没有办法通过反思来区分前面的例子和下面的例子:

public class Base {
    public virtual void Method() { }
}

public class Derived : Base {
    public new void Method() { }
}

在这种情况下,Derived 类也声明并反映了一个名为 Method 的成员。

【问题讨论】:

  • GetBaseDefinition() 应该区分这两种情况,我猜。
  • @JeppeStigNielsen:是的;这是一个更好的答案。
  • @JeppeStigNielsen:你完全正确。我错过了它,因为我使用的是 MemberInfo 而不是 MethodInfo。如果你把它变成答案,我会接受!

标签: c# reflection polymorphism


【解决方案1】:

遮蔽virtual 方法的方法将在Attributes 中设置VtableLayoutMask 标志。

请注意,普通的virtual 方法(与基类型没有相似名称)也将设置此标志。

这个标志似乎表明该方法在 VTable 中引入了一个新条目。

【讨论】:

  • 只是在 LINQPad 中玩耍,确实如此。 +1 非常值得!
  • 如果我理解您的回答,听起来好像VtableLayoutMask 属性表明该方法是否可以被覆盖,而不是它是否被覆盖。特别是,如果新方法被声明为public new virtual void Method(),那么同样无法判断它是否会影响基本方法(这里没有)。
  • @CSJ: 没有。new virtualVtableLayoutMask(因为它引入了一个新的 Vtable 条目); override 没有。
  • @SLaks:啊,抱歉,我误会了。我认为阴影意味着压倒一切;实际上这意味着使用new 关键字。总之,我应该寻找没有 VtableLayoutMask 属性。
  • VtableLayoutMask 实际上不是一个属性的名称,它是一个位掩码。调试器在枚举方面不够聪明,无法显示好的信息。位掩码仅测试属性中的一位,您确实要查找 MethodAttributes.NewSlot。如果未设置,则可以假定默认值 MethodAttributes.ReuseSlot
【解决方案2】:

有一个更具体的类MethodInfo 派生自MemberInfo。请注意,并非所有类型的成员都可以是虚拟的(例如,字段不能)。

如果你说

var derivedMethodInfo = typeof(Derived).GetMethod("Method");

那你可以检查一下

derivedMethodInfo.GetBaseDefinition() == derivedMethodInfo

或者不。请参阅documentation for GetBaseDefinition(),他们也有代码示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    相关资源
    最近更新 更多