I got here after reading this and I didn\'t find a relevant answer - So please don\'t mark this as a duplicate until you read the whole question.
I\'ve been using a refl
I think there is some confusion elsewhere on this page. Please notice that there's a difference between numbers 3 and 4!. Another point that is easily mistaken is that the base.Equals instance method (#1) calls RuntimeHelpers.Equals version, and not its own static method Object.ReferenceEquals.
virtual bool ((Object)this).Equals(Object)
[link to source][__DynamicallyInvokable] public virtual bool Equals(object obj) => RuntimeHelpers.Equals(this, obj);This is the instance method in the
Objectbase class. As noted above, this avoids infinite recursion by calling theRuntimeHelpersversion which cannot be overridden.
static bool Object.Equals(Object, Object)
[link to source]public static bool Equals(Object objA, Object objB) { if (objA == objB) return true; if (objA == null || objB == null) return false; return objA.Equals(objB); }
static bool Object.ReferenceEquals(Object, Object)
[link to source][ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [NonVersionable, __DynamicallyInvokable] public static bool ReferenceEquals(Object objA, Object objB) { return objA == objB; }Results in the simplest runtime code. Usually ends up inlined with a trivial CPU comparison of the handle values for the two reference types. Does not call user-defined
Equalsoverrides and makes no attempt to equate non reference-types by any means. That is, no two value types, blittable primitives, enums, etc. will ever equate.
static bool RuntimeHelpers.Equals(Object, Object)
[link to source][MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical] public new static extern bool Equals(object o1, object o2);Notice the
externkeyword: there is no IL code; this jumps directly to a CLR-internal code. Also beware that this is anewslotstatic method, so you must qualify this with "R̲u̲n̲t̲i̲m̲e̲H̲e̲l̲p̲e̲r̲s̲.Equals" at any call site or you'll get the very different behavior of the instance method (#2)Object.Equals.
override bool ((ValueType)this).Equals(Object)
[link to source](Not shown)
Probably subject to JIT interception anyway. May end up at runtimecallablewrapper.cpp.
There's much more to discuss here. A major factor is that a lot of the behavior is heavily influenced or intercepted by special JIT processing some of which might depend on whether an instance encountered at runtime can possibly be a value type, or whether the JIT can rule that out. I'm no expert on these matters either, so feel free to comment and/or correct. Let me know if there's interest in more detail on the JIT results, and I might be able to expand this a bit.