gpt4 book ai didi

vb.net - 在没有选中/未选中关键字支持的情况下覆盖 VB 中的 GetHashCode?

转载 作者:行者123 更新时间:2023-12-03 10:54:24 24 4
gpt4 key购买 nike

所以我想弄清楚如何正确覆盖GetHashCode()在 VB 中用于大量自定义对象。稍作搜索,我找到了 this wonderful answer .

除了有一个问题:VB 缺少 checkedunchecked .NET 4.0 中的关键字。据我所知,无论如何。因此,使用 Jon Skeet 的实现,我尝试在具有三个主要成员的相当简单的类上创建这样的覆盖:Name As String , Value As Int32 , 和 [Type] As System.Type .因此,我想出了:

Public Overrides Function GetHashCode() As Int32
Dim hash As Int32 = 17

hash = hash * 23 + _Name.GetHashCode()
hash = hash * 23 + _Value
hash = hash * 23 + _Type.GetHashCode()
Return hash
End Function

问题:对于像这样的简单对象,Int32 太小了。我测试的特定实例将“名称”作为一个简单的 5 个字符的字符串,并且仅该哈希就足够接近 Int32 的上限,当它尝试计算哈希的第二个字段(值)时,它会溢出。因为我找不到粒度 checked 的 VB 等效项/ unchecked支持,我无法解决这个问题。

我也不想在整个项目中删除整数溢出检查。这件事可能已经完成了....40%(这是我编的,TBH),而且我还有很多代码要编写,所以我需要在相当长的一段时间内进行这些溢出检查。

Jon 的 GetHashCode 的“安全”版本是什么? VB 和 Int32 的版本?或者,.NET 4.0 是否有 checked/ unchecked在我在 MSDN 上不容易找到的某个地方?

编辑:
根据链接的 SO 问题, unloved answers 之一在最底部提供了一个准解决方案。我说准是因为感觉它是……作弊。不过,乞丐不能挑剔,对吧?

从 C# 翻译成更易读的 VB 并与上述对象(名称、值、类型)对齐,我们得到:
Public Overrides Function GetHashCode() As Int32
Return New With { _
Key .A = _Name, _
Key .B = _Value, _
Key .C = _Type
}.GetHashCode()
End Function

这显然会触发编译器通过生成一个匿名类型来“作弊”,然后它会在项目命名空间之外进行编译,大概禁用整数溢出检查,并允许进行数学运算并在溢出时简单地回绕。似乎也涉及到 box操作码,我知道这会影响性能。不过没有拆箱。

但这提出了一个有趣的问题。无数次,我在这里和其他地方看到它指出 VB 和 C# 都生成相同的 IL 代码。这显然不是 100% 的情况......就像使用 C# 的 unchecked关键字只会导致发出不同的操作码。那么为什么我会继续看到两者都产生完全相同的 IL 的假设不断重复呢?

无论如何,我宁愿找到一个可以在每个对象模块中实现的解决方案。从 ILDASM 的角度来看,必须为我的每一个对象创建匿名类型看起来会很困惑。当我说我的项目中实现了很多类时,我不是在开玩笑。

EDIT2:我确实在 MSFT Connect 上打开了一个错误,VB PM 的结果的要点是他们会考虑它,但不要屏住呼吸:
https://connect.microsoft.com/VisualStudio/feedback/details/636564/checked-unchecked-keywords-in-visual-basic

快速浏览一下 .NET 4.5 的变化表明他们还没有考虑到它,所以也许是 .NET 5?

下面是我的最终实现,它符合 GetHashCode 的约束,同时对于 VB 来说仍然足够快速和独特,源自 this page 上的“旋转哈希”示例:
'// The only sane way to do hashing in VB.NET because it lacks the
'// checked/unchecked keywords that C# has.
Public Const HASH_PRIME1 As Int32 = 4
Public Const HASH_PRIME2 As Int32 = 28
Public Const INT32_MASK As Int32 = &HFFFFFFFF

Public Function RotateHash(ByVal hash As Int64, ByVal hashcode As Int32) As Int64
Return ((hash << HASH_PRIME1) Xor (hash >> HASH_PRIME2) Xor hashcode)
End Function

我也认为“Shift-Add-XOR”哈希也可能适用,但我还没有测试过。

最佳答案

这是一个结合 Hans Passant's answer 的实现和 Jon Skeet's answer .

它甚至适用于数百万个属性(即没有整数溢出异常)并且非常快(为具有 1,000,000 个字段的类生成哈希码不到 20 毫秒,而对于只有 100 个字段的类几乎无法测量)。

这是处理溢出的结构:

<StructLayout(LayoutKind.Explicit)>
Private Structure HashCodeNoOverflow
<FieldOffset(0)> Public Int64 As Int64
<FieldOffset(0)> Public Int32 As Int32
End Structure

还有一个简单的 GetHashCode 函数:
Public Overrides Function GetHashCode() As Integer

Dim hashCode As HashCodeNoOverflow

hashCode.Int64 = 17

hashCode.Int64 = CLng(hashCode.Int32) * 23 + Field1.GetHashCode
hashCode.Int64 = CLng(hashCode.Int32) * 23 + Field2.GetHashCode
hashCode.Int64 = CLng(hashCode.Int32) * 23 + Field3.GetHashCode

Return hashCode.Int32

End Function

或者,如果您喜欢:
Public Overrides Function GetHashCode() As Integer

Dim hashCode = New HashCodeNoOverflow With {.Int32 = 17}

For Each field In Fields
hashCode.Int64 = CLng(hashCode.Int32) * 23 + field.GetHashCode
Next

Return hashCode.Int32

End Function

关于vb.net - 在没有选中/未选中关键字支持的情况下覆盖 VB 中的 GetHashCode?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4654227/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com