C# 为什么'null'可以为null<;T>;你有散列码吗?

C# 为什么'null'可以为null<;T>;你有散列码吗?,c#,nullable,C#,Nullable,有点奇怪的问题 但有谁能给我一个理由来解释为什么这会是预期的行为 这对我来说真的很奇怪 //Makes perfect sense object o = null; o.GetHashCode().Dump(); NullReferenceException:对象引用未设置为 反对 0 这显然意味着: int? zero = 0; int? argh = null; zero.GetHashCode() == argh.GetHashCode(); //true 这里的重点是 int? i

有点奇怪的问题

但有谁能给我一个理由来解释为什么这会是预期的行为

这对我来说真的很奇怪

//Makes perfect sense
object o = null;
o.GetHashCode().Dump();
NullReferenceException:对象引用未设置为 反对

0

这显然意味着:

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

zero.GetHashCode() == argh.GetHashCode(); //true
这里的重点是

int? i = null;
不创建变量
i
,该变量为
null
,而是(通过执行隐式转换)一个不具有值的
null
实例。
这意味着对象/实例不是
null
(由于
null
是一种结构/值类型,它实际上不能是
null
),因此必须返回哈希代码

这也有记录:

如果HasValue属性为true,则Value属性返回的对象的哈希代码;如果HasValue属性为false,则返回零


int?
实际上只是
Nullable
的简写,这是一种结构,它包装
int
类型以允许其为null。Nullable可用于任何值类型

因为Nullable实际上是一个结构(它不能为null),所以它必须为哈希代码返回一些内容,通常它会返回值的哈希代码(大概是为了尽可能对其中的值透明)。当该值为空时,默认情况下硬编码为返回0:

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

请参阅。

它看起来像是
Nullable.GetHashCode()
的记录行为:

如果 HasValue属性为true,如果HasValue属性为false,则为零


好问题。但是请注意,仅仅因为两个hashCode相等并不意味着两个实例也相等。有趣的是,将可为null的int装箱到
object
并再次调用
GetHashCode
会产生一个NRE。这个问题超出了我的理解范围,请为我的无知道歉,但是为了我的利益,文档中提到了
Nullable.GetHashCode
如果HasValue属性为true,则Value属性返回的对象哈希代码;如果HasValue属性为false,则返回零。
。因为
HasValue
这里是
false
,所以我希望是0。这不是答案吗?int?是一个结构,语法是
可为空的
。一个结构总是有一个散列码,并且从不产生NRE。有
2^32
可能的散列码和
2^32+1
可能的可为空整数,因此至少两个
int?
必须具有相同的散列码。散列码相等的一对是0和null,这应该不会让人感到惊讶。您可能想解释一下,这是因为
Nullable
是一种值类型……好的-感谢您链接到文档。我想象一些语言设计师在同意实现之前为此争论了两周-实际上,GetHashCode应该以某种方式返回Nullable():)对象不能为null,但如果您询问它是否为null
I==null
它将返回true:-)它可能会抛出相同的NullReferenceException,而不是-哪个IMO更正确,如果它抛出一个NullReferenceException,而您有一个
哈希集
。不能向其添加空值。您将得到一个NullReferenceExection。这不是预期的行为-如果哈希集不能接受空值,为什么要使用它?您只需使用HashSet即可。如果它不抛出异常,在一般框架中更有意义,并且更适合使用Nullable,IMHO。@john,当您将
null
添加到
HashSet
时会发生什么?因此,它是否抛出NullReferenceException是无关紧要的,否则它将在null字符串情况下失败。@Arturo我承认。你说得对。代码中也有相同的“if null,hashcode is 0”逻辑,null null-nullable在这里的计算结果显然为true。因此,即使GetHashCode抛出了一个NullReferenceException,它仍然可以按预期工作。
public override int GetHashCode() {
    return hasValue ? value.GetHashCode() : 0;
}