2

I would like to understand how the GetHashCode method works on lists of objects for equality. Given this example:

var user1 = new User { Id = Guid.NewGuid().ToString(), Name = "Chris" };
var user2 = new User { Id = Guid.NewGuid().ToString(), Name = "Jeff" };

var userList1 = new List<User> { user1, user2 }.OrderBy(o => o.Id);
var userList2 = new List<User> { user1, user2 }.OrderBy(o => o.Id);

var usersList1Hash = userList1.GetHashCode();
var usersList2Hash = userList2.GetHashCode();

var userListsEqual = usersList1Hash == usersList2Hash; // false

var userList1Json = JsonConvert.SerializeObject(userList1);
var userList2Json = JsonConvert.SerializeObject(userList2);

var usersList1JsonHash = userList1Json.GetHashCode();
var usersList2JsonHash = userList2Json.GetHashCode();

var userListsJsonEqual = usersList1JsonHash == usersList2JsonHash; // true
  1. Why are the lists of objects not equal when comparing the hash codes?

  2. Why are the list of objects equal when serializing to JSON strings and comparing the hash codes?

Chris
  • 3,113
  • 5
  • 24
  • 46
  • 3
    What you're seeing is the diffference between `Object.GetHashCode()` and `String.GetHashCode()`. – Jeroen Mostert Jun 20 '19 at 09:45
  • 1
    While the lists are of the same type and contain the same objects in the same order, they are not considered equal according to their hash code. See also http://www.ideone.com/kE2gSj. – CodeCaster Jun 20 '19 at 09:49
  • @JeroenMostert Ah, okay! But what makes the `object` hashes different? – Chris Jun 20 '19 at 09:51
  • 3
    `object.GetHashCode()` generates a hash of the object reference. 2 instances = 2 different references. – Oliver Jun 20 '19 at 09:55
  • 1
    That's great. Thanks @Oliver – Chris Jun 20 '19 at 09:57
  • If you want an example of a hash function for the *contents* of a list (rather than just for the object reference) see e.g. [IEqualityComparer for SequenceEqual](https://stackoverflow.com/q/14675720/3744182). – dbc Jun 20 '19 at 09:57

1 Answers1

0

GetHashCode function gives signed int32 hash of an object.

From MSDN.

Two objects that are equal return hash codes that are equal. However, the reverse is not true: equal hash codes do not imply object equality, because different (unequal) objects can have identical hash codes.

GetHashCode is a virtual function and can be overridden. What you get after calling JsonConvert.SerializeObject function a string. string class has its own implementation of GetHashCode which is based on contents of a string. Something like below. That's why it matches.

public class string {  
  char[] str = null;
  ...
  public string(char[] input) {
    this.str = input;
  }

  public override GetHashCode() {
    //Logic to convert str to int 32 based on string contents;

    return Convert.ToInt32(str);
  }
}
Aditya Bhave
  • 998
  • 1
  • 5
  • 10
  • 3
    *"If hash of two objects is equal then objects are equal."* This is wrong. If the hash of two objects is equal, then (with a well distributed hash function) the objects are likely, but not guaranteed to be equal. This is a highly important distinction. – spender Jun 20 '19 at 10:08
  • 1
    @spender right. That's what I wanted to write. I updated the answer. – Aditya Bhave Jun 20 '19 at 10:16