The point here is that
int? i = null;
does not create a variable i which is null, but (by performing an implicit cast) a Nullable<int> instance which does not have a value.
This means the object/instance is not null (and as Nullable<T> is a struct/value type it actually can’t be null) and therefore has to return a hash-code.
This is also documented here:
The hash code of the object returned by the Value property if the HasValue property is true, or zero if the HasValue property is false.