据我了解,GetHashCode将为两个共享相同值的不同实例返回相同的值。在这一点上,MSDN文档有点模糊。
哈希码是用于标识对象的数值 在平等测试期间。
如果我有两个相同类型且具有相同值的实例,GetHashCode()将返回相同的值吗?
假设所有值都相同,以下测试是否会过去或失败?
SecurityUser只有getter和setter;
[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
}
答案 0 :(得分:8)
框架为您的自定义对象计算的哈希代码不能保证完全相同。
我认为这是因为框架没有走遍你所有的领域而且计算他们的哈希码,对每个对象来说这都是一件非常耗时的事情(我可能错了)。
这就是为什么建议您覆盖自己类型的Equals()
和GetHashCode()
方法。
答案 1 :(得分:3)
如果类SecurityUser
存储为您创建的每个用户增加的ID,则它们可能会有所不同。如果类使用它来计算它的HashCode,它们可能会有所不同。您不应该依赖GetHashCode
来测试两个对象之间的相等性。
GetHashCode
的唯一要求是objA.Equals(objB)
,然后是objA.GetHashCode() == objB.GetHashCode()
。
有关GetHashCode()
实施的详细信息,请参阅this link(“实施者须知”部分),尤其是本段:
- 如果两个对象比较相等,则为每个对象提供GetHashCode方法 对象必须返回相同的值。但是,如果两个对象没有 比较相同,两个对象的GetHashCode方法不相同 必须返回不同的值。
如果GetHashCode()
中的SecurityUser
未被覆盖,则两个HashCodes会有所不同,因为两个对象objA
和objB
是对内存中的不同对象(如new
- 关键字所示)。
答案 2 :(得分:3)
来自MSDN:
GetHashCode方法的默认实现没有 保证不同对象的唯一返回值。而且, .NET Framework不保证默认的实现 GetHashCode方法,它返回的值将是相同的 不同版本的.NET Framework。因此,默认 不得将此方法的实现用作唯一对象 用于散列目的的标识符。
GetHashCode方法可以被派生类型覆盖。值 类型必须覆盖此方法以提供哈希函数 适合该类型并在a中提供有用的分布 哈希表。为了唯一性,哈希码必须基于值 实例字段或属性而不是静态字段或 属性。
这意味着您应该覆盖班级中的GetHashCode
。
答案 3 :(得分:1)
C#中的HashCodes并不像它们看起来那么简单。默认情况下,类不会为两个相同的实例返回相同的哈希码,您必须自己创建该行为。在特定场景中使用散列码来优化查找,但至少有一位创始开发人员说过,如果他们有机会重新开始并重新开始,那么GetHashCode()就不会成为基础对象方法之一。 / p>
答案 4 :(得分:1)
在值类型上,GetHashCode()
将为具有相同值的两个对象返回相同的哈希值。但是SecurityUser
是一个引用类型,因此,它的默认GetHashCode()
方法(继承自System.Object
,正如其他人提到的那样)返回基于对象引用的哈希。由于SecurityUser
的两个不同实例不共享相同的引用,因此它们不共享相同的哈希代码。
您可以通过覆盖GetHashCode()
中的SecurityUser
方法来覆盖此行为,以便计算类的成员而不是类本身的哈希值。确保您也覆盖Equals()
,因为这两种方法是齐头并进的。您也可以考虑重写==等于运算符。
请参阅本文中接受的答案,了解GetHashCode()
的实施示例:What is the best algorithm for an overridden System.Object.GetHashCode?