覆盖 GetHashCode [重复]
Posted
技术标签:
【中文标题】覆盖 GetHashCode [重复]【英文标题】:Overriding GetHashCode [duplicate] 【发布时间】:2011-05-13 12:46:30 【问题描述】:如您所知,GetHashCode 返回一个半唯一值,可用于标识集合中的对象实例。作为一种好的做法,建议重写此方法并实现您自己的方法。
我的问题是 - 您在处理自定义对象时会覆盖此方法吗?如果是这样,您使用什么算法来生成唯一 ID?
我正在考虑生成一个 GUID,然后从该标识符获取整数数据。
【问题讨论】:
阅读this question 及其答案。它概述了一个好的哈希码实现。对于可变对象 here 覆盖GetHashCode
也有很好的讨论。
我不知道“半唯一”是什么意思......一个值要么是唯一的,要么不是,而且哈希码不是唯一的。因此,它不允许您识别列表中的对象。覆盖GetHashCode
不是“一个好习惯”,这是您需要 时要做的事情(例如,将对象用作字典中的键),而不是因为您认为这是一个好习惯练习。
使用对象作为键可以被认为是识别集合中的对象——这正是我寻找关于什么是构建标识符的最佳算法的输入的原因。截至半唯一 ID:west-wind.com/Weblog/posts/4741.aspx
丹尼斯,你首先需要考虑你想要什么样的平等行为。对于默认的引用相等(对于具有标识的可变对象),您无需执行任何操作。
【参考方案1】:
如果您使用 resharper,它可以为您生成 GetHashCode()、Equals 和运算符方法体。
按 Alt+Insert 访问此菜单。
http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html
【讨论】:
【参考方案2】:当您覆盖GetHashCode()
时,您还需要覆盖Equals()
、operator==
和operator!=
。并且要非常小心地满足这些方法的所有要求。
指南是here on MSDN。最重要的一句话:
在可变类型中覆盖 operator == 不是一个好主意。
【讨论】:
据我了解,这没有任何意义,因为对象不会改变它的状态。 什么没有意义? 字符串是不可变的,你没用过name == "x"
吗?
是的,但是当你修改一个字符串时,你会创建一个新对象(例如当你使用替换时)。
关键是,在重新分配变量之前,依靠 == 保持真实是很自然的;让突变副作用改变 == 过去的含义并不直观,因为默认情况下支持比较运算符的任何东西都是值类型或不可变的。这些仅在您说 var = "new value" 时才更改值,这明确暗示先前的 == 可能不再正确。引用类型可以从其他代码中改变状态,而在其他地方改变对象的方法可以改变相等性。 Equals 不提供相同的期望,因为它是一个方法定义,而不是语法。【参考方案3】:
在我个人的使用中,我也只在覆盖 equals 方法时覆盖。通常,我会为我知道可能会对其运行 LINQ to Objects 查询或其他一些比较操作的对象执行此操作。
如果说 LINQ to SQL 实体或 DTO 对象,我通常会返回主键值。无论返回什么,如果不将值存储在本地,可能会产生意想不到的结果。
HTH。
【讨论】:
【参考方案4】:我通常会覆盖数据类(即值语义有意义的类)的哈希码和相等检查方法。查看this question 以获得常见的实现。如果您确实覆盖哈希码覆盖等于。使用 GUID 是一个非常糟糕的主意,因为您希望两个不同实例但具有相同 值 的对象具有相同的哈希码,并且等于返回 true。
【讨论】:
【参考方案5】:您只需要在覆盖 Equals 时覆盖 GetHashCode。默认的 GetHashCode 由运行时以您想要的类似方式实现 - 每个对象都有一个由运行时分配的隐藏字段。
How to override GetHashCode
实际上,您的 IDE 应该为您执行此操作 - 当您键入“override GetHashCode”时,IDE 应该生成此样板代码。 Visual Studio 不这样做,但 SharpDevelop 会。
【讨论】:
GetHashCode 方法的默认实现不保证不同对象的返回值唯一。因此,此方法的默认实现不得用作散列目的的唯一对象标识符。来自:msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx 在 VS 中必须使用equals
sn-p 代替
@brain - 我读过这个。这是否意味着当您想将对象存储在字典中时,您应该始终覆盖 GetHashCode?我不这么认为——几乎没有人这样做。对于 Dictionary 的目的,默认实现可以正常工作。它并不完美,但很好:***.com/questions/750947/net-unique-object-identifier【参考方案6】:
通常我使用类的组件属性中聚合的 GetHashCode。例如
public class Test
public string Text get; set;
public int Age get; set;
public override GetHashCode()
int result =
string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode()
+ Age.GetHashCode();
return result;
【讨论】:
这不是一个很好的方法,请参阅***.com/questions/263400/… 一般来说,添加不利于创建复合哈希码。但在这个具体的例子中,我认为它没有问题。但当然,不覆盖 Equals 的覆盖 GetHashCode 没有多大意义。 嗯,你每天都能学到一些东西!以上是关于覆盖 GetHashCode [重复]的主要内容,如果未能解决你的问题,请参考以下文章
如果在覆盖 Equals() 时未能覆盖 GetHashCode(),会出现啥问题? [复制]