title: Why would Microsoft want NOT to fix the wrong implementations of Equals and GetHashCode with NaN?
body: <p>In the .NET Framework, the implementation (<code>override</code>) of <code>Equals(object)</code> and <code>GetHashCode()</code> for floating-point types (<code>System.Double</code> and <code>System.Single</code>) is <strong>wrong</strong>. To quote from the <a href="http://msdn.microsoft.com/en-us/library/system.object.gethashcode">MSDN <code>GetHashCode(object)</code> specification</a>:</p>
  
  <blockquote>
    <p>A hash function must have the following properties:</p>
    
    <p>• If two objects compare as equal, the GetHashCode method for each object must
    return the same value. However, if two objects do not compare as equal, the
    GetHashCode methods for the two object do not have to return different values.</p>
  </blockquote>
  
  <p>If you take two <code>NaN</code> values with different binary representations, the two objects do compare equal under the <code>Equals</code> method, but the hash codes are (almost always) distinct.</p>
  
  <p>Now, this error has <a href="http://connect.microsoft.com/VisualStudio/feedback/details/648567/">been reported</a> on Microsoft Connect. <strong>But why will they not fix this?</strong></p>
  
  <p>The fix is easy: Either let different <code>NaN</code> <em>not</em> compare as equal, or choose a fixed hash code to return for any <code>NaN</code>.</p>
  
  <p>The fix won't break anything: The way things are today, nothing works when different <code>NaN</code> are used.</p>
  
  <p>Can you think of <em>any</em> reason not to fix this?</p>
  
  <p>Here's a simple example illustrating the current behavior:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  
  static class Program
  {
    const int setSize = 1000000; // change to higher value if you want to waste even more memory
    const double oneNaNToRuleThemAll = double.NaN;
    static readonly Random randomNumberGenerator = new Random();
  
    static void Main()
    {
      var set = new HashSet&lt;double&gt;();   // uses default EqualityComparer&lt;double&gt;
  
      while (set.Count &lt; setSize)
        set.Add(GetSomeNaN());
  
      Console.WriteLine("We now have a set with {0:N0} members", set.Count);
      bool areAllEqualToTheSame = set.All(oneNaNToRuleThemAll.Equals);
      if (areAllEqualToTheSame)
        Console.WriteLine("By transitivity, all members of the set are (pairwise) equal.");
    }
  
    static double GetSomeNaN()  // can also give PositiveInfinity, NegativeInfinity (unlikely)
    {
      byte[] b = new byte[8];
      randomNumberGenerator.NextBytes(b);
      b[7] |= 0x7F;
      b[6] |= 0xF0;
      return BitConverter.ToDouble(b, 0);
    }
  }
  </code></pre>
  
  <p>Result of running the code: One million duplicates in a <code>HashSet&lt;&gt;</code>.</p>
  
  <p>PLEASE NOTE: This has <strong>nothing</strong> at all to do with the <code>==</code> and <code>!=</code> operators of C#. Please use <code>Equals</code> if you want to check this for yourself.</p>