<p>Implementing Equals() for reference types is harder than it seems. My current canonical implementation goes like this:</p>

<pre><code>public bool Equals( MyClass obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null they are not equal because in C# this cannot be null.
  if( ReferenceEquals( obj, null ) )
   return false;

   // Compare data to evaluate equality    
   return _data.Equals( obj._data );
}

public override bool Equals( object obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null or is of a different types the objects are not equal. 
  if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
    return false;

  // Use type-safe equality comparison
  return Equals( (MyClass)obj );
}

public override int GetHashCode()
{
  // Use data's hash code as our hashcode  
  return _data.GetHashCode();
}
</code></pre>

<p>I think that this covers all corner (inheritance and such) cases but I may be wrong. What do you guys think?</p>

[{'answer_id': 74540, 'author': 'Peter Ritchie', 'author_id': 5620, 'author_profile': 'https://Stackoverflow.com/users/5620', 'pm_score': 0, 'selected': False, 'text': '<p>It depends on whether you\'re writing a value type or a reference type.  For a sortable value type, I recommend this:\n<a href="http://msmvps.com/blogs/peterritchie/archive/2006/03/25/a-code-snippet-for-visual-studio-2005-that-implements-a-skeleton-value-type-adhering-to-framework-design-guidelines.aspx" rel="nofollow noreferrer">A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines</a></p>\n'}, {'answer_id': 74559, 'author': 'chakrit', 'author_id': 3055, 'author_profile': 'https://Stackoverflow.com/users/3055', 'pm_score': 0, 'selected': False, 'text': '<p>Concerning inheritance, I think you should just let the OO paradigm does its magic.</p>\n\n<p>Specifically, the <code>GetType()</code> check should be removed, it might break polymorphism down the line.</p>\n'}, {'answer_id': 74704, 'author': 'Santiago Palladino', 'author_id': 12791, 'author_profile': 'https://Stackoverflow.com/users/12791', 'pm_score': 0, 'selected': False, 'text': '<p>I agree with chakrit, objects of different types should be allowed to be semantically equal if they have the same data or ID.</p>\n\n<p>Personally, I use the following:</p>\n\n<pre><code>    public override bool Equals(object obj)\n    {\n        var other = obj as MyClass;\n        if (other == null) return false;\n\n        return this.data.Equals(other.data);\n    }\n</code></pre>\n'}, {'answer_id': 74765, 'author': 'tvanfosson', 'author_id': 12950, 'author_profile': 'https://Stackoverflow.com/users/12950', 'pm_score': 1, 'selected': False, 'text': "<p>Better hope that this._data is not null if it's also a reference type.</p>\n\n<pre><code>public bool Equals( MyClass obj )\n{\n    if (obj == null) {\n        return false;\n    }\n    else {\n        return (this._data != null &amp;&amp; this._data.Equals( obj._data ))\n                         || obj._data == null;\n    }\n}\n\npublic override bool Equals( object obj )\n{\n    if (obj == null || !(obj is MyClass)) {\n        return false;\n    }\n    else {\n        return this.Equals( (MyClass)obj );\n    }\n}\n\npublic override int GetHashCode() {\n    return this._data == null ? 0 : this._data.GetHashCode();\n}\n</code></pre>\n"}, {'answer_id': 74802, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 3, 'selected': True, 'text': '<p>I wrote a fairly comprehensive guide to this a while back. For a start your equals implementations should be shared (i.e. the overload taking an object should pass through to the one taking a strongly typed object). Additionally you need to consider things such as your object should be immutable because of the need to override GetHashCode. More info here:</p>\n\n<p><a href="http://gregbeech.com/blog/implementing-object-equality-in-dotnet" rel="nofollow noreferrer">http://gregbeech.com/blog/implementing-object-equality-in-dotnet</a></p>\n'}, {'answer_id': 69503610, 'author': 'Manfred', 'author_id': 411428, 'author_profile': 'https://Stackoverflow.com/users/411428', 'pm_score': 0, 'selected': False, 'text': '<p>As the link in the accepted answer by Greg Beech is broken, I hope this answer might be helpful to some.</p>\n<p>Microsoft\'s documentation provides the following example for a typical implementation of <code>Equals()</code> on reference types (i.e. class):</p>\n<pre class="lang-cs prettyprint-override"><code>public override bool Equals(object obj) =&gt; this.Equals(obj as TwoDPoint);\n\npublic bool Equals(TwoDPoint p)\n{\n   if (p is null)\n   {\n         return false;\n   }\n\n   // Optimization for a common success case.\n   if (Object.ReferenceEquals(this, p))\n   {\n         return true;\n   }\n\n   // If run-time types are not exactly the same, return false.\n   if (this.GetType() != p.GetType())\n   {\n         return false;\n   }\n\n   // Return true if the fields match.\n   // Note that the base class is not invoked because it is\n   // System.Object, which defines Equals as reference equality.\n   return (X == p.X) &amp;&amp; (Y == p.Y);\n}\n</code></pre>\n<p>The complete example with more details including what to do in derived classes or for structs, can be found at <a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type" rel="nofollow noreferrer">&quot;How to define value equality for a class or struct (C# Programming Guide)&quot;</a></p>\n<p>As an alternative to what is described in Microsoft\'s doc, the method <code>GetHashCode()</code> can also be implemented as follows:</p>\n<pre class="lang-cs prettyprint-override"><code>public override int GetHashCode()\n{\n   return HashCode.Combine(X, Y);\n}\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/74514', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/12851/']