如何在VB.NET中实现GetStableHash方法

本文关键字:实现 GetStableHash 方法 NET VB | 更新日期: 2023-09-27 18:28:03

我已经在几个论坛上问过这个问题,但没有很好地解释为什么上面的代码不能从C#转换到Visual Basic。

代码实际上来自这个论坛,用C#编写。(来源)

static public int GetStableHash(string s)
       {
           uint hash = 0;
            // if you care this can be done much faster with unsafe 
            // using fixed char* reinterpreted as a byte*
            foreach (byte b in System.Text.Encoding.Unicode.GetBytes(s))
            {
                hash += b;
                hash += (hash << 10);
                hash ^= (hash >> 6);
            }
            // final avalanche
            hash += (hash << 3);
            hash ^= (hash >> 11);
            hash += (hash << 15);
            // helpfully we only want positive integer < MUST_BE_LESS_THAN
            // so simple truncate cast is ok if not perfect
            return (int)(hash % MUST_BE_LESS_THAN);
       }

因此,代码应该类似于VB.NET 中的代码

    Const MUST_BE_LESS_THAN As Integer = 100000000
Function GetStableHash(ByVal s As String) As Integer

    Dim hash As UInteger = 0
    For Each b as Byte In System.Text.Encoding.Unicode.GetBytes(s)
        hash += b
        hash += (hash << 10)
        hash = hash Xor (hash >> 6)
    Next
    hash += (hash << 3)
    hash = hash Xor (hash >> 11)
    hash += (hash << 15)
    Return Int(hash Mod MUST_BE_LESS_THAN)
End Function

这似乎是对的,但不起作用。在VB.NET中,在"hash+=(hash<<10)"

如何在VB.NET中实现GetStableHash方法

处存在溢出

溢出检查在C#中默认关闭,但在VB.NET中默认打开。Project+属性,"编译"选项卡,向下滚动,"高级编译选项",并勾选"删除整数溢出检查"选项。

如果这让您感到不舒服,那么将代码移到一个单独的类库项目中,这样设置更改就不会影响代码的其余部分。另一个项目现在也可能是C#项目:)

正如Hans所解释的,您会得到一个错误,因为VB正在进行溢出检查,而C#没有。在没有溢出检查的情况下,任何多余的位都会被丢弃。您可以通过在计算过程中使用较大的数据类型并手动丢弃多余的位来复制这种相同的行为。它需要额外的1行代码,或者如果你想让答案与C#完全匹配,则需要额外的3行代码(查找注释):

Public Shared Function GetStableHash(ByVal s As String) As Integer
  ' Use a 64-bit integer instead of 32-bit
  Dim hash As ULong = 0
  For Each b As Byte In System.Text.Encoding.Unicode.GetBytes(s)
     hash += b
     hash += (hash << 10)
     ' Throw away all bits beyond what a UInteger can store
     hash = hash And UInteger.MaxValue
     hash = hash Xor (hash >> 6)
  Next
  hash += (hash << 3)
  ' Throw away all extra bits
  hash = hash And UInteger.MaxValue
  hash = hash Xor (hash >> 11)
  hash += (hash << 15)
  ' Throw away all extra bits
  hash = hash And UInteger.MaxValue
  Return Int(hash Mod MUST_BE_LESS_THAN)
End Function

如果您对与C#代码产生的结果略有不同(但同样有效)感到满意,那么您唯一需要的额外代码行就是For Each循环中的代码行。你可以删除另外两个。