How to compare two objects correctly in order to determine whether instances of objects are the same instance or not?
What is the right / best to use: Object.ReferenceEquals method

if(Object.ReferenceEquals(a, b)) { /*...*/ } 

or Operator ==

 if(a == b) { /*...*/ } // object a, b; 

ATTENTION: do not confuse Equals with ReferenceEquals

  • @VladD "Already: ru.stackoverflow.com/a/454619/10105" - there is another. Оператор == and Object.Equals . "On the same topic: blogs.msdn.microsoft.com/ericlippert/2009/04/09/…" - then in 2009 there was no open source .NET and you had to take a word for it. - Stack
  • one
    And for what a minus? Good question. - VladD February
  • @VladD "A good question" - if so, then put a plus) - Stack

2 answers 2

It seems to me that not the technical side of the question is more important here, but the readability of the code.

If you have two objects a and b , and you compare them with == , it is not the operator == (object, object) that is called, but the overloaded comparison operator. This means that the semantics == broader than a simple comparison of links.

If your goal is to recognize exactly the same instance, I would advise you to use ReferenceEquals , since at the same time you directly “say” what you want. The advantage in the compactness of the code at == , in my opinion, gives an insufficient gain compared to the advantage in clarity of the code. And for correctness of the comparison, it is necessary to cast the type to object , which also does not add brevity.


On the other hand, if you need to establish not equality of links , but the logical identity of objects, for this it may be more correct to use the (possibly overloaded) operator == . So use what you need. There is no universal advice; each method has its own application.


Another technical detail is that in current (generic-) methods (C # 6) it is impossible to tell the compiler that the type has the == operator. Therefore, a comparison via == in a generic method may not give the same result as in a regular method.

    In the .NET Framework source , the Object.ReferenceEquals method is defined as follows:

     public static bool ReferenceEquals (Object objA, Object objB) { return objA == objB; } 

    Оператор == is called in the method, so if you compare Objects , there is no difference.


    The implementation of Equals is as follows

     public static bool Equals(Object objA, Object objB) { if (objA==objB) { return true; } if (objA==null || objB==null) { return false; } return objA.Equals(objB); } 

    ATTENTION : if the Оператор == returns false, then the public virtual bool Equals(Object obj) method can be called - the virtual method can be redefined in derived classes and you should not rely on it.


    For identification, you can use the RuntimeHelpers.GetHashCode method

     using System.Runtime.CompilerServices; if(RuntimeHelpers.GetHashCode(a) == RuntimeHelpers.GetHashCode(b)) { /*... */ } 

    ATTENTION: if a and b are strings, then RuntimeHelpers.GetHashCode for identical strings may return different hash codes.

    For example,

     var s1 = "321"; var s2 = String.Concat(new List<string> { "3", "2", "1" }); var r1 = s1 == s2; // true var r2 = RuntimeHelpers.GetHashCode(s1) == RuntimeHelpers.GetHashCode(s2); // false 

    The fact is that literals (strings defined in the code, such as "321") are added to the internal string pool in order to save memory.
    And the rows collected from the parts are not added to the pool. Therefore, it turns out that s1 and s2 are different objects.
    But s2 can be interned (i.e. add to the string pool)

     s2 = String.Intern(s2); 

    Because the string pool already has s1, then s2 and s1 will point to the same string object, so the hash codes for s1 and s2 will become equal.

     var r3 = RuntimeHelpers.GetHashCode(s1) == RuntimeHelpers.GetHashCode(s2); // true 
    • Comments are not intended for extended discussion; conversation moved to chat . - PashaPash