Почему Microsoft хотела бы НЕ исправить неправильные реализации Equals и GetHashCode с помощью NaN?

В .NET Framework реализация (override) Equals(object) и GetHashCode() для типов с плавающей точкой (System.Double и System.Single) неверна. Чтобы процитировать из MSDN GetHashCode(object) спецификацию:

Функция хеширования должна иметь следующие свойства:

• Если два объекта сравниваются как равные, метод GetHashCode для каждого объекта должен вернуть одно и то же значение. Однако, если два объекта не сравниваются как равные, Методы GetHashCode для двух объектов не должны возвращать разные значения.

Если вы берете два значения NaN с разными двоичными представлениями, два объекта сравниваются равными по методу Equals, но хэш-коды (почти всегда) отличаются.

Теперь эта ошибка содержит в Microsoft Connect. Но почему они не исправят это?

Исправить легко: либо пусть разные NaN не сравниваются как равные, либо выберите фиксированный хеш-код для возврата для любого NaN.

Исправление ничего не сломает: как это происходит сегодня, ничего не работает, когда используются разные NaN.

Можете ли вы подумать о какой-либо причине, чтобы не исправить это?

Вот простой пример, иллюстрирующий текущее поведение:

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<double>();   // uses default EqualityComparer<double>

    while (set.Count < 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);
  }
}

Результат запуска кода: миллион дубликатов в HashSet<>.

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: ничего не имеет отношения к операторам == и != оператора С#. Используйте Equals, если вы хотите проверить это самостоятельно.