F#记录的GetHashCode()是如何实现的?
How is GetHashCode() of F# record implemented?
我很难在 https://github.com/fsharp/fsharp
上找到它
这非常重要,因为我需要确保尽可能少的碰撞。
好吧,我可以告诉你,它不会提供尽可能少的碰撞。您可能想要覆盖 GetHashCode。有些人抱怨它不符合他们的散列需求,但为了向后兼容,它不能合理地改变。如果出于检查冲突哈希的性能考虑,这对您来说是一个严重的问题,我会在 github visual fsharp 存储库中添加一个问题。
更新,来源:
github.com/fsharp/fslang-suggestions/issues/366
github.com/fsharp/fsharp/issues/343
github.com/Microsoft/visualfsharp/issues/1838
正如 VoroniPotato 所提到的,您可能想自己覆盖 GetHashCode
,但 GetHashCode
的默认实现如下所示。假设fields
是记录中字段值的列表,那么做如下步骤:
从初始值 0 开始。
然后对于字段中的每个元素,从最后一个定义的元素开始(即给定记录类型 {a: int; b: string}
我们从 b
开始),执行以下操作:
0x9e3779b9 + fields.[i].GetHashCode() + (value <<< 6) + (value >>> 2)
,其中值是算法上一次迭代的值。我们假设 fields.[i]
不为空,否则它的哈希值只是设置为 0.
对所有字段重复步骤 2。
您可以在 mkRecdHashWithComparer and mkAddToHashAcc 的代码中的源代码中看到这一点。
{a: int; b: string}
的简单示例记录,反编译后的GetHashCode
方法是这样的:
[CompilerGenerated]
public sealed override int GetHashCode(IEqualityComparer comp)
{
if (this != null)
{
int num = 0;
num = -1640531527 + ((b@?.GetHashCode() ?? 0) + ((num << 6) + (num >> 2)));
return -1640531527 + (a@ + ((num << 6) + (num >> 2)));
}
return 0;
}
我很难在 https://github.com/fsharp/fsharp
上找到它这非常重要,因为我需要确保尽可能少的碰撞。
好吧,我可以告诉你,它不会提供尽可能少的碰撞。您可能想要覆盖 GetHashCode。有些人抱怨它不符合他们的散列需求,但为了向后兼容,它不能合理地改变。如果出于检查冲突哈希的性能考虑,这对您来说是一个严重的问题,我会在 github visual fsharp 存储库中添加一个问题。
更新,来源: github.com/fsharp/fslang-suggestions/issues/366 github.com/fsharp/fsharp/issues/343 github.com/Microsoft/visualfsharp/issues/1838
正如 VoroniPotato 所提到的,您可能想自己覆盖 GetHashCode
,但 GetHashCode
的默认实现如下所示。假设fields
是记录中字段值的列表,那么做如下步骤:
从初始值 0 开始。
然后对于字段中的每个元素,从最后一个定义的元素开始(即给定记录类型
{a: int; b: string}
我们从b
开始),执行以下操作:0x9e3779b9 + fields.[i].GetHashCode() + (value <<< 6) + (value >>> 2)
,其中值是算法上一次迭代的值。我们假设fields.[i]
不为空,否则它的哈希值只是设置为 0.对所有字段重复步骤 2。
您可以在 mkRecdHashWithComparer and mkAddToHashAcc 的代码中的源代码中看到这一点。
{a: int; b: string}
的简单示例记录,反编译后的GetHashCode
方法是这样的:
[CompilerGenerated]
public sealed override int GetHashCode(IEqualityComparer comp)
{
if (this != null)
{
int num = 0;
num = -1640531527 + ((b@?.GetHashCode() ?? 0) + ((num << 6) + (num >> 2)));
return -1640531527 + (a@ + ((num << 6) + (num >> 2)));
}
return 0;
}