Определите, представляют ли два экземпляра MethodInfo один и тот же (не виртуальный) метод посредством наследования

Сначала я приведу простой пример, где я знаю ответ. Рассматривать:

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

Мы видим, что am а также gm не считаются равными, что вполне справедливо (последнее является переопределением первого). Однако с последней строкой мы можем определить, что эти два метода связаны; один является "базовым методом" другого.

(Вы даже можете проверить равенство ссылок, (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?

В этом случае pn а также tn все еще считаются разными (и их ReflectedType отличается).

Как я могу проверить, действительно ли они (через наследование) один и тот же метод?

Есть ли встроенный метод в рамках? Если мне придется решить это вручную, какова стратегия? Должен ли я проверить, что оба имеют одинаковые DeclaringType, имеют одинаковые списки (типов) параметров и имеют одинаковое количество параметров типа?

1 ответ

Решение

Вы можете использовать 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
Другие вопросы по тегам