Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,125 | Comments: 45,488

filter by tags archive

Method Equality

time to read 2 min | 283 words

The CLR team deserve a truly great appreciation for making generics works at all. When you get down to it, it is amazingly complex. Most of the Rhino Mocks bugs stems from having to work at that level. Here is one example,  comparing method equality. Let us take this simple example:

public class WeirdStuff
	public class Test<T>
		public void Compare()

	public void ThisIsWeird()
		new Test<int>().Compare();

This is one of those things that can really bites you. And it fails only if the type is a generic type, even though the comparison is made of the closed generic version of the type. Finding the root cause was fairly hard, and naturally the whole thing is internal, but eventually I managed to come up with a way to compare them safely:

private static bool AreMethodEquals(MethodInfo left, MethodInfo right)
	if (left.Equals(right))
		return true;
	// GetHashCode calls to RuntimeMethodHandle.StripMethodInstantiation()
	// which is needed to fix issues with method equality from generic types.
	if (left.GetHashCode() != right.GetHashCode())
		return false;
	if (left.DeclaringType != right.DeclaringType)
		return false;
	ParameterInfo[] leftParams = left.GetParameters();
	ParameterInfo[] rightParams = right.GetParameters();
	if (leftParams.Length != rightParams.Length)
		return false;
	for (int i = 0; i < leftParams.Length; i++)
		if (leftParams[i].ParameterType != rightParams[i].ParameterType)
			return false;
	if (left.ReturnType != right.ReturnType)
		return false;
	return true;

The secret here is with the call to GetHashCode, which remove the method instantiation code, which is fairly strange concept, because I wasn't aware that you can instantiate methods :-)


Mark Monster

What do you mean by method instantiation? Instantiation using delegates for named and anonymous method?

Ayende Rahien

I mean by the method object itself, no delegates involved.

This is probably mentioned in the docs, but I have no idea where


Nice solution. What about method access privileges on each? What if one method is public and the other is internal or protected? Should they still be considered equal to each other?

Thomas Krause

Shouldn't you also check the method name for equality?

Two methods could be declared on the same class with the same signature (parameters and return type) but different names. The Hash code will of course be different in most of the cases, but this isn't guaranteed... Am I missing something here?

Ayende Rahien

Yes, because if it has the same declaring type, and the same name & parameters, you can define another method with a different name

Ayende Rahien

Thomas ,

Great catch, I'll add that


"the comparison is made of the closed generic version of the type" - actually, it's not. GetType().GetMethod("Compare").DeclaringType is closed. MethodInfo.GetCurrentMethod().DeclaringType is open. See the Community Content section for MethodBase.GetCurrentMethod for details:


Basically, MethodBase.GetCurrentMethod doesn't behave as one would expect.

Also notice that ContainsGenericParameters is false in the first MethodInfo while it is true in the second. According to the following link, this means the second one is an open constructed generic method:


Comment preview

Comments have been closed on this topic.


  1. The design of RavenDB 4.0: Physically segregating collections - 4 hours from now
  2. RavenDB 3.5 Whirlwind tour: I need to be free to explore my data - about one day from now
  3. RavenDB 3.5 whirl wind tour: I'll have the 3+1 goodies to go, please - 4 days from now
  4. The design of RavenDB 4.0: Voron has a one track mind - 5 days from now
  5. RavenDB 3.5 whirl wind tour: Digging deep into the internals - 6 days from now

And 12 more posts are pending...

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    03 May 2016 - Making Lucene reliable
  2. RavenDB 3.5 whirl wind tour (14):
    04 May 2016 - I’ll find who is taking my I/O bandwidth and they SHALL pay
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats