Учитывая, что такие коллекции, как System.Collections.Generic.HashSet<> accept null как член набора, можно спросить, каков должен быть хэш-код null. Похоже, что в структуре используется 0:
// nullable struct type
int? i = null;
i.GetHashCode();  // gives 0
EqualityComparer<int?>.Default.GetHashCode(i);  // gives 0
// class type
CultureInfo c = null;
EqualityComparer<CultureInfo>.Default.GetHashCode(c);  // gives 0
Это может быть (немного) проблематично с нулевыми перечислениями. Если мы определим
enum Season
{
  Spring,
  Summer,
  Autumn,
  Winter,
}
 то Nullable<Season> (также называемый Season?) может принимать только пять значений, но два из них, а именно null и Season.Spring, имеют одинаковый хэш-код.
Возникает соблазн написать "лучшее" сравнительное равенство:
class NewNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? Default.GetHashCode(x) : -1;
  }
}
Но есть ли причина, по которой хэш-код null должен быть 0?
EDIT/Сложение:
Некоторые люди, похоже, думают, что это касается переопределения Object.GetHashCode(). На самом деле это не так. (Авторы .NET сделали переопределение GetHashCode() в структуре Nullable<>, которая имеет .) Пользовательская реализация без параметров GetHashCode() никогда не сможет справиться с ситуацией где объект, чей хэш-код мы ищем, null.
Речь идет об использовании абстрактного метода EqualityComparer<T>.GetHashCode(T) или иным способом реализации метода интерфейса IEqualityComparer<T>.GetHashCode(T), Теперь, создавая эти ссылки на MSDN, я вижу, что там говорится, что эти методы бросают ArgumentNullException, если их единственным аргументом является null. Это, безусловно, ошибка в MSDN? Ни одна из собственных реализаций .NET не выдает исключений. Бросание в этом случае эффективно нарушит любую попытку добавить null к HashSet<>. Если HashSet<> делает что-то необычное при работе с элементом null (мне нужно будет это проверить).
NEW EDIT/ADDITION:
Теперь я попробовал отладку. С помощью HashSet<> я могу подтвердить, что с помощью сопоставителя равенства по умолчанию значения Season.Spring и null  будут заканчиваться в том же ведре. Это можно определить, тщательно проверив частные элементы массива m_buckets и m_slots. Обратите внимание, что индексы всегда, по дизайну, смещены на один.
Однако приведенный выше код не исправляет это. Как оказалось, HashSet<> никогда не спросит о равенстве, когда значение null. Это из исходного кода HashSet<>:
    // Workaround Comparers that throw ArgumentNullException for GetHashCode(null).
    private int InternalGetHashCode(T item) {
        if (item == null) { 
            return 0;
        } 
        return m_comparer.GetHashCode(item) & Lower31BitMask; 
    }
Это означает, что , по крайней мере, для HashSet<>, даже не возможно изменить хэш null. Вместо этого решение должно изменить хэш всех других значений, например:
class NewerNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? 1 + Default.GetHashCode(x) : /* not seen by HashSet: */ 0;
  }
}
