Value vs. Reference equality in generic List<T>.Contains()
<h3>Attempt #3 to simplify this question:</h3>
<p>A generic <code>List&lt;T&gt;</code> can contain any type - value or reference.  When checking to see if a list contains an object, <code>.Contains()</code> uses the default <code>EqualityComparer&lt;T&gt;</code> for type T, and calls <code>.Equals()</code> (is my understanding).  If no EqualityComparer has been defined, the default comparer will call <code>.Equals()</code>.  By default, <code>.Equals()</code> calls <code>.ReferenceEquals()</code>, so <code>.Contains()</code> will only return true if the list contains the exact same object.</p>
<p>Until you need to override <code>.Equals()</code> to implement value equality, at which point the default comparer says two objects are the same if they have the same values.  I can't think of a single case where that would be desirable for a reference type.</p>
<p>What I'm hearing from @Enigmativity is that implementing <code>IEqualityComparer&lt;StagingDataRow&gt;</code> will give my typed DataRow a default equality comparer that will be used instead of the default comparer for <code>Object</code> – allowing me to implement value equality logic in <code>StagingDataRow.Equals()</code>.</p>
<p>Questions:</p>
<ol>
<li>Am I understanding that correctly?</li>
<li>Am I guaranteed that everything in the .NET framework will call <code>EqualityComparer&lt;StagingDataRow&gt;.Equals()</code> instead of <code>StagingDataRow.Equals()</code>?</li>
<li>What should <code>IEqualityComparer&lt;StagingDataRow&gt;.GetHashCode(StagingDataRow obj)</code> hash against, and should it return the same value as <code>StagingDataRow.GetHashCode()</code>?</li>
<li>What is passed to <code>IEqualityComparer&lt;StagingDataRow&gt;.GetHashCode(StagingDataRow obj)</code>?  The object I'm looking for or the object in the list?  Both?  It would be strange to have an instance method accept itself as a parameter...</li>
</ol>
<p>In general, how does one separate value equality from reference equality when overriding <code>.Equals()</code>?</p>
<br />
<hr />
<p>The original line of code spurring this question:</p>
<pre><code>//  For each ID, a collection of matching rows
Dictionary&lt;string, List&lt;StagingDataRow&gt;&gt; stagingTableDictionary;


StagingTableMatches.AddRange(stagingTableDictionary[perNr].Where(row =&gt; !StagingTableMatches.Contains(row)));

.
</code></pre>
<br />