为什么当两个相同类型的对象具有相同的值时,哈希码会不同?

7 浏览
0 Comments

为什么当两个相同类型的对象具有相同的值时,哈希码会不同?

我的理解是,如果两个不同的实例具有相同的值,GetHashCode方法将返回相同的值。然而,MSDN文档在这一点上有些含糊不清。\n如果我有两个相同类型且具有相同值的实例,GetHashCode方法会返回相同的值吗?\n假设所有的值都相同,以下测试会通过还是失败?\nSecurityUser只有getter和setter方法。\n[TestMethod]\npublic void GetHashCode_Equal_Test()\n{\n SecurityUser objA = new SecurityUser(EmployeeName, EmployeeNumber, LastLogOnDate, Status, UserName);\n SecurityUser objB = new SecurityUser(EmployeeName, EmployeeNumber, LastLogOnDate, Status, UserName);\n int hashcodeA = objA.GetHashCode();\n int hashcodeB = objB.GetHashCode();\n Assert.AreEqual(hashcodeA, hashcodeB);\n}\n///

\n/// 这个类代表了AppSecurity中的一个SecurityUser实体。\n///

\npublic sealed class SecurityUser\n{\n #region [Constructor]\n ///

\n /// 使用传入的参数初始化SecurityUser类的新实例。\n ///

\n /// 要初始化的员工姓名。\n /// 要初始化的员工编号。\n /// 要初始化的最后登录日期。\n /// 要初始化的SecurityStatus。\n /// 要初始化的用户名。 \n public SecurityUser(\n string employeeName,\n int employeeNumber, \n DateTime? lastLogOnDate,\n SecurityStatus status,\n string userName)\n {\n if (employeeName == null)\n throw new ArgumentNullException(\"employeeName\");\n if (userName == null)\n throw new ArgumentNullException(\"userName\");\n this.EmployeeName = employeeName;\n this.EmployeeNumber = employeeNumber;\n this.LastLogOnDate = lastLogOnDate;\n this.Status = status;\n this.UserName = userName;\n }\n #endregion\n #region [Properties]\n ///

\n /// 获取当前实例的员工姓名。\n ///

\n public string EmployeeName { get; private set; }\n ///

\n /// 获取当前实例的员工编号。\n ///

\n public int EmployeeNumber { get; private set; }\n ///

\n /// 获取当前实例的最后登录日期。\n ///

\n public DateTime? LastLogOnDate { get; private set; }\n ///

\n /// 获取当前实例的用户名。\n ///

\n public string UserName { get; private set; }\n ///

\n /// 获取当前实例的SecurityStatus。\n ///

\n public SecurityStatus Status { get; private set; }\n #endregion\n}

0
0 Comments

当两个相同类型的对象具有相同的值时,它们的哈希码可能不同。这可能是因为类SecurityUser存储了一个随着每个创建的用户而增加的ID。如果类使用这个ID来计算其哈希码,它们很可能是不同的。你不应该依赖于GetHashCode来测试两个对象之间的相等性。

对于GetHashCode的唯一要求是:如果objA.Equals(objB),那么objA.GetHashCode() == objB.GetHashCode()

参见此链接("Notes to Implementers"节)中关于GetHashCode()的实现细节,特别是这一段:

  • 如果两个对象比较相等,那么每个对象的GetHashCode方法必须返回相同的值。然而,如果两个对象不相等,那么两个对象的GetHashCode方法不必返回不同的值。

如果SecurityUser中没有重写GetHashCode(),则两个哈希码将不同,因为objAobjB是指向内存中不同对象的引用(如new关键字所示)。

0
0 Comments

当两个相同类型的对象具有相同的值时,为什么哈希码会不同?

在上述MSDN中提到,GetHashCode方法的默认实现不能保证对不同对象返回唯一的哈希码。此外,.NET Framework也不能保证GetHashCode方法的默认实现,而且它返回的值在不同版本的.NET Framework中将是相同的。因此,不能将这个方法的默认实现用作唯一的对象标识符。

为了解决这个问题,可以在类中重写GetHashCode方法。对于值类型,必须重写这个方法,以提供适合该类型的哈希函数,并在哈希表中提供有用的分布。为了保证唯一性,哈希码必须基于实例字段或属性的值,而不是静态字段或属性。

所以,为了确保当两个相同类型的对象具有相同的值时哈希码相同,需要重写GetHashCode方法,并基于实例字段或属性的值来计算哈希码。这样可以提供一个适合该类型的哈希函数,使得相同值的对象具有相同的哈希码。

0
0 Comments

当两个相同类型的对象具有相同的值时,为什么哈希码会不同?

哈希码是根据对象的内容计算得出的,而不是根据对象的引用。因此,即使两个对象的值相同,它们的引用不同,哈希码也会不同。

这是因为框架为自定义对象计算哈希码时,并不保证哈希码是相同的。框架并不会遍历所有字段并计算它们的哈希码,这样做对于每个对象来说是非常耗时的。

为了解决这个问题,建议在自定义类型上重写Equals()和GetHashCode()方法。重写GetHashCode()方法将基于对象的内容计算哈希码,而不是基于引用。

如果不重写GetHashCode()方法,那么生成的哈希码将是object.GetHashCode()的结果,它只是返回一个由CLR确定的基于引用的数字。

因此,如果创建两个空对象,它们的类型相同,但是它们将返回不同的哈希码。

为了确保哈希码的一致性,建议始终重写GetHashCode()方法。特别是在依赖于默认的Equals()、'=='和'!='功能或在使用哈希集合时。如果需要进行复杂的匹配测试并需要额外的参数,则建议实现自定义的Match()方法。

0