Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if two MethodInfo instances represent the same (non-virtual) method through inheritance

First I give a simple example where I know the answer. Consider:

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

and then somewhere the code:

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

We see that am and gm are not considered equal, which is entirely fair (the latter is an override of the former). However, with the last line we can determine that these two methods are related; one is a "base method" of the other.

(You can even check for reference equality, (object)am == (object)gm.GetBaseDefinition(), and you still get True.)

And now for the situation I have a question for. Consider instead:

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

with:

  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?

In this case pn and tn are still considered different (and their ReflectedType differ).

How can I test whether they are in fact (through inheritance) the same method?

Is there any built-in method in the framework? If I will have to work out this by hand, what is the strategy? Must I check that both have same DeclaringType, have identical lists of (types of) paramaters, and have the same number of type parameters?

like image 469
Jeppe Stig Nielsen Avatar asked Sep 26 '22 20:09

Jeppe Stig Nielsen


1 Answers

You can use the DeclaringType property:

am.DeclaringType.Dump(); // Animal
gm.DeclaringType.Dump(); // Giraffe

pn.DeclaringType.Dump(); // Plant
tn.DeclaringType.Dump(); // Plant

Or you can use MethodHandle:

(am.MethodHandle == gm.MethodHandle).Dump(); // False

(pn.MethodHandle == tn.MethodHandle).Dump(); // True

Though I'm not sure if this is entirely reliable.

If you only care about whether the method is actually overriden in a given type, you can also use the BindingFlags:

var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null
like image 153
Luaan Avatar answered Sep 30 '22 08:09

Luaan