Why is (object)0 == (object)0 different from ((object)0).Equals((object)0)?

Why are the following expressions different?

[1]  (object)0 == (object)0 //false
[2]  ((object)0).Equals((object)0) // true

Actually, I can totally understand [1] because probably the .NET runtime will box the integer and start comparing the references instead. But why is [2] different?


The reason the calls behave different is they bind to very different methods.

The == case will bind to the static reference equality operator. There are 2 independent boxed int values created hence they are not the same reference.

In the second case you bind to the instance method Object.Equals. This is a virtual method which will filter down to Int32.Equals and this checks for a boxed integer. Both integer values are 0 hence they are equal


When you cast the int value 0 (or any other value type) to object, the value is boxed. Each cast to object produces a different box (i.e. a different object instance). The == operator for the object type performs a reference comparison, so it returns false since the left-hand side and right-hand side are not the same instance.

On the other hand, when you use Equals, which is a virtual method, it uses the implementation of the actual boxed type, i.e. Int32.Equals, which returns true since both objects have the same value.


The == operator, being static, is not virtual. It will run the exact code that the object class defines (`object being the compile time type of the operands), which will do a reference comparison, regardless of the runtime type of either object.

The Equals method is a virtual instance method. It will be running the code defined in the actual run-time type of the (first) object, not the code in the object class. In this case, the object is an int, so it will perform a value comparison, as that is what the int type defines for its Equals method.


The Equals() method is virtual.
Therefore, it always calls the concrete implementation, even when the callsite is casted to object. int overrides Equals() to compare by value, so you get value comparison.


== Use: Object.ReferenceEquals

Object.Equals compares the value.

The object.ReferenceEquals method compares references. When you allocate an object, you receive a reference containing a value indicating its memory location in addition to the object's data on the memory heap.

The object.Equals method compares the contents of objects. It first checks whether the references are equal, as does object.ReferenceEquals. But then it calls into derived Equals methods to test equality further. See this:

   System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b);  //returns true