Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are hashcodes different when two objects of the same type have the same values?

It is my understanding that GetHashCode will return the same value for two different instances which share the same values. The MSDN documentation is a bit fuzzy on this point.

A hash code is a numeric value that is used to identify an object during equality testing.

If I have two instances of the same type and the same values will the GetHashCode() return the same value?

Assuming all the values are the same, would the following test past or fail?

SecurityUser only has getters and setters;

    [TestMethod]
    public void GetHashCode_Equal_Test()
    {
        SecurityUser objA = new SecurityUser(EmployeeName, EmployeeNumber, LastLogOnDate, Status, UserName);
        SecurityUser objB = new SecurityUser(EmployeeName, EmployeeNumber, LastLogOnDate, Status, UserName);

        int hashcodeA = objA.GetHashCode();
        int hashcodeB = objB.GetHashCode();

        Assert.AreEqual<int>(hashcodeA, hashcodeB);
    }


/// <summary>
/// This class represents a SecurityUser entity in AppSecurity.
/// </summary>
public sealed class SecurityUser
{
    #region [Constructor]

    /// <summary>
    /// Initializes a new instance of the <see cref="SecurityUser"/> class using the
    /// parameters passed.
    /// </summary>
    /// <param name="employeeName">The employee name to initialize with.</param>
    /// <param name="employeeNumber">The employee id number to initialize with.</param>
    /// <param name="lastLogOnDate">The last logon date to initialize with.</param>
    /// <param name="status">The <see cref="SecurityStatus"/> to initialize with.</param>
    /// <param name="userName">The userName to initialize with.</param>        
    public SecurityUser(
        string employeeName,
        int employeeNumber,            
        DateTime? lastLogOnDate,
        SecurityStatus status,
        string userName)
    {
        if (employeeName == null)
            throw new ArgumentNullException("employeeName");

        if (userName == null)
            throw new ArgumentNullException("userName");

        this.EmployeeName = employeeName;
        this.EmployeeNumber = employeeNumber;
        this.LastLogOnDate = lastLogOnDate;
        this.Status = status;
        this.UserName = userName;
    }

    #endregion

    #region [Properties]

    /// <summary>
    /// Gets the employee name of the current instance.
    /// </summary>
    public string EmployeeName { get; private set; }

    /// <summary>
    /// Gets the employee id number of the current instance.
    /// </summary>
    public int EmployeeNumber { get; private set; }

    /// <summary>
    /// Gets the last logon date of the current instance.
    /// </summary>
    public DateTime? LastLogOnDate { get; private set; }

    /// <summary>
    /// Gets the userName of the current instance.
    /// </summary>
    public string UserName { get; private set; }

    /// <summary>
    /// Gets the <see cref="SecurityStatus"/> of the current instance.
    /// </summary>
    public SecurityStatus Status { get; private set; }

    #endregion
}
like image 427
Chuck Conway Avatar asked Dec 03 '22 23:12

Chuck Conway


1 Answers

Hash codes calculated by the framework for your custom objects aren't guaranteed to be identical.

I believe this is due to the framework not walking all your fields and such and calculating their hashcodes, it would be such a time-expensive thing to do for every object (I may be wrong).

This is why it is recommended that you override the Equals() and GetHashCode() methods on your own types.

See: Overriding GetHashCode

like image 188
Clint Avatar answered Dec 24 '22 13:12

Clint