我正在尝试创建一个简单的磁盘缓存,但每次运行应用程序时,我的结构相等的记录都有不同的哈希值。
当我在 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
我希望运行
hash
在结构相等的记录上总是返回相同的值。
最佳答案
F# underneat 使用标准的 .NET 散列函数。每次执行新进程(或旧 .NET 框架中的 AppDomain)时,它们都会应用一个特殊的随机种子。这使得它们在不同的过程中不一致。这样做的原因是安全性:保持哈希不变将是一个漏洞,可用于例如。确定性哈希冲突攻击。
如果你想要快速一致的哈希,你需要像 Murmur3 或 CityHash 这样的东西。它们在散列任何字节序列方面非常快,并提供了相当好的冲突避免。但是,它们在 F#/.NET 中不受开箱即用的支持。
如果你想使用 .NET 标准库中已经存在的东西,你可能会使用 MD5,但请记住,它的速度比上面两个要弱得多。它也被认为更容易发生碰撞。
关于.net-core - 为什么散列 F# 记录在每次运行时返回不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56800639/