I've already asked this question on several forums, but without any good explanation of why the code above cannot be converted from C# to Visual Basic.
The code is actually from this forum, written in 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);
}
So, the code ought to be something like that in 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
It seems to be right, but it does not work. In VB.NET, there is an overflow at "hash += (hash << 10)"
Overflow checking is off by default in C# but on by default in VB.NET. Project + Properties, Compile tab, scroll down, Advanced Compile Options and tick the "Remove integer overflow checks" option.
If that makes you uncomfortable then move the code into a separate class library project so the setting change doesn't affect the rest of your code. That other project could now also be a C# project :)
As Hans explained, you are getting an error because VB is doing overflow checking and C# is not. Without overflow checking, any extra bits are simply thrown away. You can replicate this same behavior by using a larger data type during the calculation and throwing the extra bits away manually. It takes 1 extra line of code, or 3 extra lines of code if you want the answers to match C# exactly (look for the comments):
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
If you are OK with slightly different results (but equally valid) from what the C# code produces, the only extra line of code you need is the one inside the For Each
loop. You can delete the other two.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.