GetHashCode() 为相同的对象值返回不同的值
GetHashCode() Returning Different Values For Identical Object Values
我试图使用 GetHashCode()
值来确定对象在通过 ASP.NET MVC 应用程序中的 ajax 调用进行验证后是否已更改。但是,我注意到这不起作用,因为在验证期间返回的哈希码值将不同于在验证请求之后从模型绑定中再次创建对象时生成的哈希码,该模型绑定具有相同的值。我能够通过创建 SHA 哈希来解决这个问题,但我很好奇为什么我会看到这种行为。
我知道从 GetHashCode()
生成的散列码不应该保留,并且随着时间的推移在不同的平台上可能会有所不同。当我第一次想到这个想法时,我认为时间段已经足够短了,因为这两个调用彼此相差几毫秒,并且在调试时我确认模型包含完全相同的值,但仍然产生了不同的哈希码。
我很好奇为什么会出现这种行为。为什么即使这是应用程序的单个 运行(尽管是 Web 应用程序)也会发生这种情况?这与 ASP.NET 生命周期有关吗?
如果需要,这里是我使用的 class & GetHashCode 实现:
class DispositionSubmission
{
[Display(Name = "Client")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Client is required.")]
public string ClientId { get; set; }
public string Carrier { get; set; }
public Dictionary<string, string> DispositionInfo { get; set; }
public DispositionType Type { get; set; } //int based enum
...
public override int GetHashCode()
{
unchecked
{
int hash = (int)15485863;
int bigPrime = (int)15485867;
hash = hash * bigPrime ^ ClientId.GetHashCode();
hash = hash * bigPrime ^ (Carrier ?? "").GetHashCode();
hash = hash * bigPrime ^ DispositionInfo.GetHashCode();
hash = hash * bigPrime ^ Type.GetHashCode();
return hash;
}
}
}
DispositionInfo
没有覆盖 GetHashCode()
的类型。两个具有相同对象的相同字典将具有不同的哈希码。
您需要调整 GetHashCode()
以不包含字典或使其更复杂以获取字典中每个键和值的哈希码并将它们相加。
GetHashCode
将 return 对完全相同的对象产生相同的结果。如果该对象已被重新分配,即使您在所有字段中具有相同的值也没关系,您将得到不同的结果。这是因为您真正使用的是 Object.GetHashCode()
,它对其他字段一无所知。
此行为很重要,因为如果您使用散列作为引用对象的方式,更改其任何值将无法再次引用。
如果您希望具有相同字段的对象具有相同哈希码的行为,您需要自己实现。
编辑:澄清一下:DispositionInfo
,字典,特别表现出这种行为。其他字段没有,因为它们被设计为不可变的(字符串、整数等)考虑以不同的方式获取哈希,或者使用继承自 [=14 的自定义 class 覆盖 GetHashCode
=].
我试图使用 GetHashCode()
值来确定对象在通过 ASP.NET MVC 应用程序中的 ajax 调用进行验证后是否已更改。但是,我注意到这不起作用,因为在验证期间返回的哈希码值将不同于在验证请求之后从模型绑定中再次创建对象时生成的哈希码,该模型绑定具有相同的值。我能够通过创建 SHA 哈希来解决这个问题,但我很好奇为什么我会看到这种行为。
我知道从 GetHashCode()
生成的散列码不应该保留,并且随着时间的推移在不同的平台上可能会有所不同。当我第一次想到这个想法时,我认为时间段已经足够短了,因为这两个调用彼此相差几毫秒,并且在调试时我确认模型包含完全相同的值,但仍然产生了不同的哈希码。
我很好奇为什么会出现这种行为。为什么即使这是应用程序的单个 运行(尽管是 Web 应用程序)也会发生这种情况?这与 ASP.NET 生命周期有关吗?
如果需要,这里是我使用的 class & GetHashCode 实现:
class DispositionSubmission
{
[Display(Name = "Client")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Client is required.")]
public string ClientId { get; set; }
public string Carrier { get; set; }
public Dictionary<string, string> DispositionInfo { get; set; }
public DispositionType Type { get; set; } //int based enum
...
public override int GetHashCode()
{
unchecked
{
int hash = (int)15485863;
int bigPrime = (int)15485867;
hash = hash * bigPrime ^ ClientId.GetHashCode();
hash = hash * bigPrime ^ (Carrier ?? "").GetHashCode();
hash = hash * bigPrime ^ DispositionInfo.GetHashCode();
hash = hash * bigPrime ^ Type.GetHashCode();
return hash;
}
}
}
DispositionInfo
没有覆盖 GetHashCode()
的类型。两个具有相同对象的相同字典将具有不同的哈希码。
您需要调整 GetHashCode()
以不包含字典或使其更复杂以获取字典中每个键和值的哈希码并将它们相加。
GetHashCode
将 return 对完全相同的对象产生相同的结果。如果该对象已被重新分配,即使您在所有字段中具有相同的值也没关系,您将得到不同的结果。这是因为您真正使用的是 Object.GetHashCode()
,它对其他字段一无所知。
此行为很重要,因为如果您使用散列作为引用对象的方式,更改其任何值将无法再次引用。
如果您希望具有相同字段的对象具有相同哈希码的行为,您需要自己实现。
编辑:澄清一下:DispositionInfo
,字典,特别表现出这种行为。其他字段没有,因为它们被设计为不可变的(字符串、整数等)考虑以不同的方式获取哈希,或者使用继承自 [=14 的自定义 class 覆盖 GetHashCode
=].