【问题标题】:How to implement GetStableHash method in VB.NET如何在 VB.NET 中实现 GetStableHash 方法
【发布时间】:2015-07-10 05:40:42
【问题描述】:

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

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

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 处有溢出

【问题讨论】:

    标签: c# vb.net


    【解决方案1】:

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

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

    【讨论】:

    • 在 VB.net 中是否无法更改单个文件/文件的一部分的溢出检查?类似于 C# unchecked 关键字?
    • 不,该语言中没有关键字。不可能,溢出检查是由语言语法假设的。这就是为什么您不必强制转换以将 int 分配给字节的原因。
    【解决方案2】:

    正如 Hans 所解释的,您收到错误是因为 VB 正在执行溢出检查而 C# 没有。如果没有溢出检查,任何额外的位都会被简单地丢弃。您可以通过在计算期间使用更大的数据类型并手动丢弃额外的位来复制相同的行为。如果您希望答案与 C# 完全匹配,则需要 1 行额外的代码或 3 行额外的代码(查找 cmets):

    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 循环中的那一行。您可以删除其他两个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多