Type Design: Equals and HashCode

Good type design dictates that the Equals should always be overridden. This is actually a FXCop violation but 99.99% of types that I see, never has it (or GetHashCode).  Overriding Equals is pretty easy.

    Public  Overloads  Function  Equals(ByVal  obj As  [Object] ) As  Boolean 
       Try 
          Dim  ci = DirectCast (obj, ComputerInfo )
          Return  (ci.OSFullName = Me.OSFullName) And
                    (ci.OSPlatform = Me.OSPlatform)
       Catch 
          Return  False 
       End  Try 
    End  Function

The issue with overriding Equals like shown in the code above, is maintenance. Any developer that adds a property will have to remember to add that property to the statement above. Good luck keeping this up to date. I wrote the following method to help with this issue.

    Public  Function  DoesObjectEqualInstance(ByVal  obj As  [Object] , 
                                              ByVal  instance As  Object )
                                              As  Boolean 
        For  Each  prop As  PropertyInfo  In  obj.GetType.GetProperties()
          If  Not  prop.GetValue(obj, Nothing )
             .Equals(instance.GetType.GetProperty(prop.Name)
             .GetValue(instance, Nothing )) Then 
             Return  False 
          End  If 
       Next 
        Return  True 
     End  Function

Now your Equals statement should look like this:

    Public  Overloads  Function  Equals(ByVal  obj As  [Object] ) As  Boolean 
       Return  General.DoesObjectEqualInstance(Me , obj)
    End  Function

GetHashCode should also be overridden in the same manner for the same reasons. Here is the code and an example:

    Public  Function  GetInstanceHashCode(ByVal  instance As  Object ) As  Int32 
       Dim  hash As  Int32 
        For  Each  prop As  PropertyInfo  In  instance.GetType.GetProperties()
          Dim  value = prop.GetValue(instance, Nothing )
          hash = hash Xor  value.GetHashCode
       Next 
       Return  hash
     End  Function
    Public  Overloads  Overrides  Function  GetHashCode() As  Integer 
       Return  General.GetInstanceHashCode(Me )
    End  Function

Note: This code uses reflection which is not as fast if you coded it yourself, but it’s much more maintainable.

Tip By: David McCarter

This code can be found in the dotNetTips.Utility open source project.

One thought on “Type Design: Equals and HashCode

  1. Bill Wagner explains another reason for overriding HashCode in the case where you’re using your type as a key in dictionaries. The default hash code for reference types potentially violates some of the requirements for a dictionary key. You have to be very careful when using reference types as dictionary keys, and probably should avoid it if you haven’t thought it through pretty carefully.

Comments are closed.