确定两个MethodInfo实例是否通过继承表示相同(非虚拟)方法

本文关键字:继承 表示 方法 虚拟 是否 两个 MethodInfo 实例 | 更新日期: 2023-09-27 18:10:58

首先我给出一个我知道答案的简单例子。考虑:

class Animal
{
  public virtual void M() { Console.WriteLine("a"); }
}
class Giraffe : Animal
{
  public override void M() { Console.WriteLine("g"); }
}

,然后在某处代码:

  var am = typeof(Animal).GetMethod("M");
  var gm = typeof(Giraffe).GetMethod("M");
  Console.WriteLine(am == gm);  // False
  Console.WriteLine(am == gm.GetBaseDefinition());  // True

我们看到amgm不被认为是相等的,这是完全公平的(后者是对前者的覆盖)。然而,通过最后一行,我们可以确定这两个方法是相关的;一个是另一个的"基方法"。

(你甚至可以检查引用是否相等,(object)am == (object)gm.GetBaseDefinition(),你仍然得到True.)

现在我有一个问题。考虑相反:

class Plant
{
  public void N() /* non-virtual */ { }
}
class Tree : Plant
{
}

:

  var pn = typeof(Plant).GetMethod("N");
  var tn = typeof(Tree).GetMethod("N");
  Console.WriteLine(pn == tn);  // False
  // How can I determine that 'pn' and 'tn' are in a sense the same method?

在这种情况下,pntn仍然被认为是不同的(它们的ReflectedType不同)。

如何测试它们是否实际上(通过继承)是相同的方法?

框架中是否有任何内置方法?如果我必须手工算出来,策略是什么?我必须检查两者是否具有相同的DeclaringType,具有相同的(类型的)参数列表,并且具有相同数量的类型参数吗?

确定两个MethodInfo实例是否通过继承表示相同(非虚拟)方法

您可以使用DeclaringType属性:

am.DeclaringType.Dump(); // Animal
gm.DeclaringType.Dump(); // Giraffe
pn.DeclaringType.Dump(); // Plant
tn.DeclaringType.Dump(); // Plant

或者你可以使用MethodHandle:

(am.MethodHandle == gm.MethodHandle).Dump(); // False
(pn.MethodHandle == tn.MethodHandle).Dump(); // True

虽然我不确定这是否完全可靠。

如果您只关心方法是否在给定类型中被实际覆盖,您还可以使用BindingFlags:

var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null