为什么散列 F# 记录 return 每个 运行 上的不同值

Why does hashing an F# record return a different value on each run

我正在尝试创建一个简单的磁盘缓存,但每次我 运行 应用程序时,我的结构相同的记录都有不同的哈希值。

当我在 LINQPad 中 运行 或记录仅包含整数时,行为似乎是正确的(确定性的)。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

</Project>
type Test = { test : string }

[<EntryPoint>]
let main argv =
    { test = "test" }
    |> hash
    |> printfn "%i"

    0

我希望 运行ning hash 在结构相同的记录上总是 return 相同的值。

F# underneat 使用标准的 .NET 散列函数。每次执行新进程(或旧 .NET 框架中的 AppDomain)时,它们都会应用一个特殊的随机种子。这使得它们在不同过程中不一致。这样做的原因是安全性:保持散列不变将是一个漏洞,可用于例如。确定性哈希冲突攻击。

如果你想拥有快速一致的哈希值,你需要像 Murmur3 或 CityHash 这样的东西。它们在散列任何字节序列时速度非常快,并提供相当好的避免冲突。但是,它们在 F#/.NET 中不受开箱即用的支持。

如果你想使用 .NET 标准库中已经存在的东西,你可能会使用 MD5,但请记住它的速度比上面两个弱得多。它也被认为更容易发生碰撞。