title: Overriding GetHashCode in VB without checked/unchecked keyword support?
body: <p>So I'm trying to figure out how to correctly override <code>GetHashCode()</code> in VB for a large number of custom objects.  A bit of searching leads me to <a href="https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode">this wonderful answer</a>.</p>
  
  <p>Except there's one problem: VB lacks both the <code>checked</code> and <code>unchecked</code> keyword in .NET 4.0.  As far as I can tell, anyways.  So using Jon Skeet's implementation, I tried creating such an override on a rather simple class that has three main members: <code>Name As String</code>, <code>Value As Int32</code>, and <code>[Type] As System.Type</code>.  Thus I come up with:  </p>
  
  <pre><code>Public Overrides Function GetHashCode() As Int32
      Dim hash As Int32 = 17
  
      hash = hash * 23 + _Name.GetHashCode()
      hash = hash * 23 + _Value
      hash = hash * 23 + _Type.GetHashCode()
      Return hash
  End Function
  </code></pre>
  
  <p>Problem: Int32 is too small for even a simple object such as this.  The particular instance I tested has "Name" as a simple 5-character string, and that hash alone was close enough to Int32's upper limit, that when it tried to calc the second field of the hash (Value), it overflowed.  Because I can't find a VB equivalent for granular <code>checked</code>/<code>unchecked</code> support, I can't work around this.</p>
  
  <p>I also do not want to remove Integer overflow checks across the entire project.  This thing is maybe....40% complete (I made that up, TBH), and I have a lot more code to write, so I need these overflow checks in place for quite some time.</p>
  
  <p>What would be the "safe" version of Jon's <code>GetHashCode</code> version for VB and Int32?  Or, does .NET 4.0 have <code>checked</code>/<code>unchecked</code> in it somewhere that I'm not finding very easily on MSDN?
  <br/><br/><br/>
  <strong>EDIT:</strong><br>
  Per the linked SO question, one of the <a href="https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/4630550#4630550">unloved answers</a> at the very bottom provided a <em>quasi</em>-solution.  I say quasi because it feels like it's....cheating.  Beggars can't be choosers, though, right?</p>
  
  <p>Translated from from C# into a more readable VB and aligned to the object described above (Name, Value, Type), we get:</p>
  
  <pre><code>Public Overrides Function GetHashCode() As Int32
      Return New With { _
          Key .A = _Name, _
          Key .B = _Value, _
          Key .C = _Type
       }.GetHashCode()
  End Function
  </code></pre>
  
  <p>This triggers the compiler apparently to "cheat" by generating an anonymous type, which it then compiles outside of the project namespace, presumably with integer overflow checks disabled, and allows the math to take place and simply wrap around when it overflows.  It also seems to involve <code>box</code> opcodes, which I know to be performance hits.  No unboxing, though.</p>
  
  <p><strike>But this raises an interesting question.  Countless times, I've seen it stated here and elsewhere that both VB and C# generate the same IL code.  This is clearly not the case 100% of the time...Like the use of C#'s <code>unchecked</code> keyword simply causes a different opcode to get emitted.  So why do I continue to see the assumption that both produce the exact same IL keep getting repeated?</strike>&nbsp;&nbsp;&lt;/rhetorical-question&gt;</p>
  
  <p>Anyways, I'd rather find a solution that can be implemented within each object module.  Having to create Anonymous Types for every single one of my objects is going to look messy from an ILDASM perspective.  I'm not kidding when I say I have a <em>lot</em> of classes implemented in my project.
  <br /><br /><br />
  <strong>EDIT2:</strong> I did open up a bug on MSFT Connect, and the gist of the outcome from the VB PM was that they'll consider it, but don't hold your breath:
  <a href="https://connect.microsoft.com/VisualStudio/feedback/details/636564/checked-unchecked-keywords-in-visual-basic" rel="noreferrer">https://connect.microsoft.com/VisualStudio/feedback/details/636564/checked-unchecked-keywords-in-visual-basic</a></p>
  
  <p>A quick look at the changes in .NET 4.5 suggests they've not considered it yet, so maybe .NET 5?</p>
  
  <p>My final implementation, which fits the constraints of GetHashCode, while still being fast and <em>unique enough</em> for VB is below, derived from the "Rotating Hash" example on <a href="http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx" rel="noreferrer">this page</a>:</p>
  
  <pre><code>'// The only sane way to do hashing in VB.NET because it lacks the
  '// checked/unchecked keywords that C# has.
  Public Const HASH_PRIME1 As Int32 = 4
  Public Const HASH_PRIME2 As Int32 = 28
  Public Const INT32_MASK As Int32 = &amp;HFFFFFFFF
  
  Public Function RotateHash(ByVal hash As Int64, ByVal hashcode As Int32) As Int64
      Return ((hash &lt;&lt; HASH_PRIME1) Xor (hash &gt;&gt; HASH_PRIME2) Xor hashcode)
  End Function
  </code></pre>
  
  <p>I also think the "Shift-Add-XOR" hash may also apply, but I haven't tested it.</p>