title: generic reference equality comparer does not work for ValueTuple
body: <p>I have written a generic equality comparer that should always compare by reference, no matter how the <code>GetHashCode</code> and <code>Equals</code> methods of the parameter type look like:</p>
  
  <pre><code>public class ReferenceEqualityComparer&lt;T&gt; : IEqualityComparer&lt;T&gt;
  {
      public static ReferenceEqualityComparer&lt;T&gt; Inst = new ReferenceEqualityComparer&lt;T&gt;();
      private ReferenceEqualityComparer() { }
      public bool Equals(T x, T y) { return ReferenceEquals(x, y); }
  
      public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); }
  }
  </code></pre>
  
  <p>I threw in a <code>ValueTuple</code> (in this case a pair of <code>object</code>s) like so:</p>
  
  <pre><code>var objectPairComparer = ReferenceEqualityComparer&lt;(object,object)&gt;.Inst;
  </code></pre>
  
  <p>But this comparer does not behave as expected, so I guess I am doing something wrong. To see what's wrong, first consider the following situation:</p>
  
  <pre><code>object a = new object();
  object b = new object();
  
  object c = a;
  object d = b;
  
  HashSet&lt;(object, object)&gt; set = new HashSet&lt;(object, object)&gt;();
  Console.WriteLine("set.Add((a, b)) = " + set.Add((a, b))); // returns true
  Console.WriteLine("set.Contains((c, d)) = " + set.Contains((c, d))); // returns true
  Console.WriteLine("set.Add((c, d)) = " + set.Add((c, d))); // returns false
  </code></pre>
  
  <p>Since no comparer is given as input to the <code>HashSet</code>, the default comparer will be used. That means, both <code>Item1</code> and <code>Item2</code> will use reference equality and default hash code (the address or something). The output is what I expect.</p>
  
  <p>But if I instead use the comparer</p>
  
  <pre><code>HashSet&lt;(object,object)&gt; set = new HashSet&lt;(object,object)&gt;(objectPairComparer);
  </code></pre>
  
  <p>then the output changes:</p>
  
  <pre><code>Console.WriteLine("set.Add((a, b)) = " + set.Add((a, b))); // returns true like before
  Console.WriteLine("set.Contains((c, d)) = " + set.Contains((c, d))); // returns FALSE
  Console.WriteLine("set.Add((c, d)) = " + set.Add((c, d))); // returns TRUE
  </code></pre>
  
  <p>But they should behave the same way! Why don't they? Isn't <code>ReferenceEquals</code> the same as <code>object.Equals</code>, and isn't <code>ReferenceEquals</code> used on two <code>(object,object)</code> the same as using <code>ReferenceEquals</code> both on the <code>Item1</code>s and <code>Item2</code>s and <code>&amp;&amp;</code>ing the results? And <code>GetHashCode</code> analogous?</p>