Visual Studio为什么将“ -1937169414”添加到生成的哈希码计算中?

问题描述 投票:5回答:1

如果使用Visual Studio自己的重构菜单将GetHashCode实现添加到这样的类中,则:

Generate GetHashCode menu

并选择类中唯一的int属性:

Member selection screen

它在.NET Framework上生成此代码:

public override int GetHashCode()
{
    return -1937169414 + Value.GetHashCode();
}

(它代替在.NET Core上生成HashCode.Combine(Value),我不确定它是否包含相同的值)

此值有什么特别之处?为什么Visual Studio不直接使用Value.GetHashCode()?据我了解,它并不会真正影响哈希分布。由于只是加法,所以连续的值仍会累积在一起。

编辑:我仅使用具有Value属性的不同类尝试了此操作,但显然属性名称会影响生成的数字。例如,如果将属性重命名为Halue,数字将变为387336856。感谢GökhanKurt指出了这一点。

c# visual-studio
1个回答
0
投票
如注释中的GökhanKurt所述,数字根据所涉及的属性名称而变化。如果将属性重命名为Halue,该数字将改为387336856。我曾尝试过使用不同的类,但没有考虑重命名该属性。

Gökhan的评论使我明白了它的目的。它基于确定的但随机分布的偏移量来偏移哈希值。这样,即使使用简单的加法运算,将不同类的哈希值组合在一起,仍然可以稍微抵抗哈希冲突。

例如,如果您有两个具有相似的GetHashCode实现的类:

public class A { public int Value { get; set;} public int GetHashCode() => Value; } public class B { public int Value { get; set;} public override int GetHashCode() => Value; }

并且如果您有另一个包含对这两个引用的类:

public class C { public A ValueA { get; set; } public B ValueB { get; set; } public override int GetHashCode() { return ValueA.GetHashCode() + ValueB.GetHashCode(); } }

这样的不良组合将易于出现哈希冲突,因为如果ValueA和ValueB的值彼此接近,则对于哈希值A和ValueB的不同值,生成的哈希码将在同一区域周围累积。如果您使用乘法或按位运算来组合它们,实际上并不重要,如果没有均匀间隔的偏移,它们仍然很容易发生冲突。由于编程中使用的许多整数值都在0附近累积,因此使用这样的偏移量是有意义的。

显然,具有良好位模式的随机偏移是一种好习惯。

我仍然不确定为什么他们不使用完全随机的偏移量,可能不会破坏依赖于GetHashCode()确定性的任何代码,但是很高兴收到Visual Studio团队对此的评论。] >

© www.soinside.com 2019 - 2024. All rights reserved.