2012-03-17 152 views
2

我已经在几个论坛上问过这个问题,但没有任何好的解释,说明为什么上面的代码不能从C#转换为Visual Basic。如何在VB.NET中实现GetStableHash方法

代码实际上来自于这个论坛,用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,存在在“散列+ =(散列< < 10)”的溢出

回答

4

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

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

+0

有没有办法改变VB.net中单个文件/文件的一部分溢出检查?类似于C#'unchecked'关键字? – CodesInChaos 2012-03-17 16:22:32

+0

不,这个语言里没有关键字。不可能有,语言语法假定溢出检查。这就是为什么你不必强制将一个int分配给一个字节的原因。 – 2012-03-17 16:44:56

0

正如汉斯解释,你会得到一个错误,因为VB正在做溢出检查和C#不是。没有溢出检查,任何额外的位都会被丢弃。您可以通过在计算过程中使用更大的数据类型来复制相同的行为,并手动丢弃额外的位。它需要的代码1个额外的行,或代码3个额外的行,如果你想要的答案完全匹配C#(查找注释):

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 

如果你都OK略有不同的结果(但同样有效)从C#代码生成的代码中,您需要的唯一额外代码行就是For Each循环中的代码。您可以删除其他两个。

相关问题