如何确定 MethodInfo 是否是基方法的覆盖

18

我想确定从类型实例的GetMethod调用中获取的MethodInfo对象是由类型本身还是它的基类实现的。

例如:

Foo foo = new Foo();
MethodInfo methodInfo = foo.GetType().GetMethod("ToString",BindingFlags|Instance);

ToString方法可能在Foo类中实现,也可能没有。我想知道我是否得到了foo的实现?

相关问题

有没有可能判断一个派生类中是否重写了.NET虚方法?

4个回答

21

检查它的DeclaringType属性。

if (methodInfo.DeclaringType == typeof(Foo)) {
   // ...
}

2
如果被检查的方法也是抽象方法,则此方法将无法工作。这里有解释 - AlexMelw

5

不要使用反射,而是使用委托会更快!尤其是在新版本的框架中,操作非常迅速。

    public delegate string ToStringDelegate();

    public static bool OverridesToString(object instance)
    {
        if (instance != null)
        {
            ToStringDelegate func = instance.ToString;
            return (func.Method.DeclaringType == instance.GetType());
        }
        return false;
    }

太棒了!我以前从未见过这个技巧。你是怎么想出来的? - Timo

1
你需要查看DeclaringType属性。如果ToString方法来自Foo,则DeclaringType将是Foo类型。

1
您需要检查MemberInfo对象的DeclaringType属性(实际上是获取声明此成员的类)是否等于ReflectedType属性(该属性获取用于获取此MemberInfo实例的类对象)。
此外,您还需要检查属性IsAbstract。 如果它为true,则检查的方法绝对没有被重写,因为“抽象”意味着该成员是一个新声明,在当前类中不能有其实现(即“体”),而只能在派生类中存在。
以下是使用下面提供的扩展方法的示例:
Student student = new Student
{
    FirstName = "Petter",
    LastName = "Parker"
};

bool isOverridden = student.GetType()
    .GetMethod(
        name: nameof(ToString),
        bindingAttr: BindingFlags.Instance | BindingFlags.Public,
        binder: null,
        types: Type.EmptyTypes,
        modifiers: null
    ).IsOverridden(); // ExtMethod

if (isOverridden)
{
    Console.Out.WriteLine(student);
}

扩展方法:
using System.Reflection;

public static class MethodInfoHelper
{
    /// <summary>
    ///     Detects whether the given method is overridden.
    /// </summary>
    /// <param name="methodInfo">The method to inspect.</param>
    /// <returns><see langword="true" /> if method is overridden, otherwise <see langword="false" /></returns>
    public static bool IsOverridden(this MethodInfo methodInfo)
    {
        return methodInfo.DeclaringType == methodInfo.ReflectedType
               && !methodInfo.IsAbstract;
    }
}

实际上,一个方法可以重新抽象化,即使用 abstract override - jnm2
也许你正在谈论不同的事情,但是OP问如何检测方法是否为覆盖方法,而不是如何检测方法是否已被覆盖。 - jnm2
关于抽象方法:假设Animal覆盖了ToString(),然后Mammal有一个abstract overrideToString()。换句话说,Mammal重新抽象化了该方法,要求其具体子类型在某个时候重新实现它。从Mammal的角度来看,我们会认为该方法被覆盖了吗?当然,这取决于我们的定义。我们可以肯定地说一件事情,那就是该方法与_原始_实现(恰好是Object.ToString())相比肯定被覆盖了。 - Timo

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