Answered by:
Rewritting C# GetHashCode in Visual Basic with a few Questions

Question
-
User686339638 posted
Hello,
I found the following code online, but i don't know the Visual Basic equivalent. I found some pieces but i'm not sure i understand it.
// Note: Not quite FNV! public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = (int) 2166136261; // Suitable nullity checks etc, of course :) hash = hash * 16777619 ^ field1.GetHashCode(); hash = hash * 16777619 ^ field2.GetHashCode(); hash = hash * 16777619 ^ field3.GetHashCode(); return hash; } }
I reformatted this code in VB below to correct for the lack of a unchecked method
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 17 hash = hash * 16777619 ^ If(IsNothing(field1), 1, field1.GetHashCode()) hash = hash * 16777619 ^ If(IsNothing(field2), 1, field2.GetHashCode()) hash = hash * 16777619 ^ If(IsNothing(field3), 1, field3.GetHashCode()) Return CInt(hash And &H7FFFFFFFL) End Function
I got part of this from: http://stackoverflow.com/questions/4654227/overriding-gethashcode-in-vb-without-checked-unchecked-keyword-support
Few Questions:
1) Is this written correctly?
2) What does And &H7FFFFFFFL do? I don't understand this.
3) Why choose 2166136261 over 17 for the initial Long value? It seems that the longer number will reach Arithmetic Overflow a lot quicker than using smaller numbers such as 17. Is there an advantage?
Thanks very much!
Thursday, March 10, 2016 10:01 PM
Answers
-
User614698185 posted
Hi JacobPressures,
If you want to use GetHashCode method, please refer to the below link:
https://documentation.devexpress.com/#CodeRush/CustomDocument17203
Best Regards,
Candice Zhou
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, March 16, 2016 9:42 AM -
User686339638 posted
Thanks for the link Candice! Ok the following 2 code samples were overflowing on the Long int.
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = hash * 16777619 Xor If(IsNothing(PayerID), 1, PayerID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(CaseID), 1, CaseID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(EncounterID), 1, EncounterID.GetHashCode()) Return CInt(hash And &H7FFFFFFFL) End Function
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = hash * 16777619 + If(IsNothing(PayerID), 1, PayerID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(CaseID), 1, CaseID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode()) Return CInt(hash And &H7FFFFFFFL) End Function
I purposely used these numbers to test if they overflowed.
While i did not understand everything discussed in that link, I was able to get this much out, which does not overflow:
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = CInt((hash * 16777619 Xor If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = CInt((hash * 16777619 + If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
Since the two above did not overflow, I assume the smaller numbers should certainly be safe.
So here is the code I ended up using.
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 17 hash = CInt((hash * 23 + If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Thursday, March 17, 2016 7:05 PM
All replies
-
User397347636 posted
The '^' symbol in C# is the exclusive or operator - the equivalent in VB is 'XOr'.
"And &H7FFFFFFL" is a bitwise 'And' operation.
Friday, March 11, 2016 12:35 AM -
User614698185 posted
Hi JacobPressures,
hash = hash * 16777619 ^ field1.GetHashCode();As David Anton said, The '^' symbol in C# is the exclusive or operator - the equivalent in VB is 'XOr':
hash = hash * 16777619 Xor field1.GetHashCode()
2) What does And &H7FFFFFFFL do? I don't understand this.If you calculate hash as Long, but then return it as Integer with Return CInt(hash And &H7FFFFFFFL). This way could avoid the overflow.
Best Regards,
Candice Zhou
Friday, March 11, 2016 5:24 AM -
User686339638 posted
Thanks very much guys. One last question:
3) Why choose 2166136261 over 17 for the initial Long value? It seems that the longer number will reach Arithmetic Overflow a lot quicker than using smaller numbers such as 17. Is there an advantage?
Candice, you said in answer to #2: "If you calculate hash as Long, but then return it as Integer with Return CInt(hash And &H7FFFFFFFL). This way could avoid the overflow."
So does that mean that the size of the integers being multiplied doesn't matter? Should i still avoid the overflow perhaps because of degradation of precision or quality?
Thanks a lot guys!
Friday, March 11, 2016 2:53 PM -
User686339638 posted
This did not work. It resulted in an overflow. I'm not sure that code is working right.
Tuesday, March 15, 2016 3:04 PM -
User614698185 posted
Hi JacobPressures,
If you want to use GetHashCode method, please refer to the below link:
https://documentation.devexpress.com/#CodeRush/CustomDocument17203
Best Regards,
Candice Zhou
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Wednesday, March 16, 2016 9:42 AM -
User686339638 posted
Thanks for the link Candice! Ok the following 2 code samples were overflowing on the Long int.
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = hash * 16777619 Xor If(IsNothing(PayerID), 1, PayerID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(CaseID), 1, CaseID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode()) hash = hash * 16777619 Xor If(IsNothing(EncounterID), 1, EncounterID.GetHashCode()) Return CInt(hash And &H7FFFFFFFL) End Function
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = hash * 16777619 + If(IsNothing(PayerID), 1, PayerID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(CaseID), 1, CaseID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode()) hash = hash * 16777619 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode()) Return CInt(hash And &H7FFFFFFFL) End Function
I purposely used these numbers to test if they overflowed.
While i did not understand everything discussed in that link, I was able to get this much out, which does not overflow:
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = CInt((hash * 16777619 Xor If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 Xor If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 2166136261 hash = CInt((hash * 16777619 + If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 16777619 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
Since the two above did not overflow, I assume the smaller numbers should certainly be safe.
So here is the code I ended up using.
Public Overrides Function GetHashCode() As Integer Dim hash As Long = 17 hash = CInt((hash * 23 + If(IsNothing(PayerID), 1, PayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(InsuredPersonID), 1, InsuredPersonID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(CaseID), 1, CaseID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(PersonPayerID), 1, PersonPayerID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(AppointmentID), 1, AppointmentID.GetHashCode())) And &H7FFFFFFFL) hash = CInt((hash * 23 + If(IsNothing(EncounterID), 1, EncounterID.GetHashCode())) And &H7FFFFFFFL) Return CInt(hash And &H7FFFFFFFL) End Function
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Thursday, March 17, 2016 7:05 PM