c# типы - Почему «null» Nullable<T>имеет хеш-код?




проверка на (4)

Это похоже на документальное поведение Nullable<T>.GetHashCode() , поскольку в документации написано :

Хэш-код объекта, возвращаемого свойством Value, если свойство HasValue имеет значение true, или ноль, если свойство HasValue является ложным.

Немного странный вопрос ...

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

Мне это кажется совершенно странным ...

//Makes perfect sense
object o = null;
o.GetHashCode().Dump();

NullReferenceException: Ссылка на объект не установлена ​​в экземпляр объекта.

//Seems very odd
int? i = null;
i.GetHashCode().Dump();

0

Это, очевидно, означает:

int? zero = 0;
int? argh = null;

zero.GetHashCode() == argh.GetHashCode(); //true

int? на самом деле просто сокращенно для Nullable<int> , структуры, которая обертывает тип int , чтобы позволить ему быть нулевым. Nullable может использоваться с любым типом значения.

Поскольку Nullable на самом деле является структурой (она не может быть нулевой), она должна возвращать что-то для хэш-кода, и обычно она возвращает хэш-код значения (предположительно, чтобы быть как можно более прозрачным для значения внутри). Когда значение равно null, оно жестко запрограммировано на возврат 0 по умолчанию:

public override int GetHashCode() {
    return hasValue ? value.GetHashCode() : 0;
}

См. here .


Дело здесь в том, что

int? i = null;

не создает переменную i которая является null , но (путем выполнения неявного приведения) экземпляр Nullable<int> который не имеет значения.
Это означает, что объект / экземпляр не является null (и поскольку Nullable<T> является типом struct / value, он фактически не может быть null ) и поэтому должен возвращать хэш-код.

Это также описано here :

Хэш-код объекта, возвращаемого свойством Value, если свойство HasValue имеет значение true, или ноль, если свойство HasValue является ложным.


Что будет делать эта функция, если вызывается как Rec(0) (не под отладчиком)?

static void Rec(int i)
{
    Console.WriteLine(i);
    if (i < int.MaxValue)
    {
        Rec(i + 1);
    }
}

Ответ:

  • В 32-разрядном JIT это должно привести к исключению Exception
  • В 64-битном JIT он должен распечатать все числа до int.MaxValue

Это связано с тем, что 64-битный JIT-компилятор применяет оптимизацию хвостового вызова , тогда как 32-разрядная JIT-версия не работает.

К сожалению, у меня нет 64-битной машины, чтобы проверить это, но метод удовлетворяет всем условиям оптимизации хвостового вызова. Если у кого-нибудь есть, мне было бы интересно узнать, правда ли это.





c# nullable