Overriding GetHashCode
如您所知,GetHashCode返回一个半唯一值,该值可用于标识集合中的对象实例。作为一个好的实践,建议重写此方法并实现自己的方法。
我的问题是-在处理自定义对象时是否重写此方法?如果是,您使用什么算法来生成唯一的ID?
我正在考虑生成一个guid,然后从那个标识符中获取整数数据。
- 阅读这个问题及其答案。它概述了一个好的哈希代码实现。这里也有一个很好的讨论,关于易变物体过度使用GetHashCode。
- 我不知道"半独特"是什么意思…值要么是唯一的,要么不是唯一的,哈希代码也不是唯一的。因此,它不允许您标识列表中的对象。重写GetHashCode并不是"一个好的实践",这是你需要做的事情(例如,在字典中使用对象作为键),而不是因为你认为这是一个好的实践。
- 将对象用作键可以被视为标识集合中的对象——这正是我寻找构建标识符的最佳算法的输入的原因。自半唯一ID起:west-wind.com/weblog/posts/4741.aspx
- 丹尼斯,你首先需要考虑你想要什么样的平等行为。对于默认的引用相等(对于具有标识的可变对象),您必须什么也不做。
如果使用resharper,它可以为您生成gethashcode()、equals和operator方法体。
按alt+insertakbd可访问此菜单。
http://www.jetbrains.com/resharper/webhelp/code_u generation_uu equality_members.html
- jetbrains.com/resharper/webhelp/…
- 一种更简单的方法,它不会插入太多样板文件,并且在类更改时保持最新:eamonnerbonne.github.io/valueutils
- 无论什么原因,alt+insert都不会打开我的resharper菜单,但是我可以使用菜单:resharper->edit->generate code…
当您覆盖GetHashCode()时,您还需要覆盖Equals()、operator==和operator!=。并且要非常小心地满足这些方法的所有要求。
本指南在MSDN上。最重要的引用:
It is not a good idea to override operator == in non-immutable types.
- 根据我的理解,这是没有意义的,因为对象不会改变它的状态。
- 什么是没有意义的?
- 重写==运算符。
- 字符串是不可变的,您从未使用过name =="x"?
- 是的,但是当您修改字符串时,您将创建一个新对象(例如,当您使用replace时)。
- 不过,字符串重写equals和所有其他值。我不明白你的意思。
- @丹尼斯:你不能修改字符串,它是不变的。这不是语义陈述。像replace这样的调用方法返回一个新的字符串不会修改字符串,不会从字面上修改,也不会从图形上修改。你必须改变你的心态。
- 哦,不,我不是说绳子是可变的。我说的正是你刚才说的-当我调用replace时,字符串没有被修改-而是创建了一个新的对象。
- 关键是,在重新分配变量之前,依赖于==保持正确是很自然的;让突变副作用改变==的过去含义是不直观的,因为默认情况下支持比较运算符的任何内容都是值类型或不可变的。只有当您说var="new value"时,这些值才会改变,这意味着前面的==可能不再是真的。引用类型可以改变其他代码的状态,方法可以改变其他地方的对象,从而改变相等性。Equals不提供相同的期望值,因为它是一个方法定义,而不是语法。
- 只是为了澄清:不可变与可变是同一回事?
- @是的,但在命令式语言(如c)中,可变是一种规范。
我通常会重写数据类(即值语义有意义的类)的哈希代码和相等性检查方法。请看一看这个问题以获得一个通用的实现。如果您确实重写了hashcode,则重写等于。使用一个guid是一个非常糟糕的想法,因为您希望两个不同实例但具有相同值的对象具有相同的哈希代码,而for equals返回true。
在我的个人用法中,我只在重写equals方法时重写。通常,我会为我知道可以对其运行linq-to-objects查询或其他比较操作的对象执行此操作。
如果说linq to sql实体或dto对象,我通常返回主键值。无论返回什么,如果不在本地存储该值,它可能会产生意外的结果。
Hth.
仅当重写equals时才需要重写gethashcode。默认的gethashcode由运行时以您希望的类似方式实现-每个对象都有一个由运行时分配的隐藏字段。
如何重写GetHashCode
实际上,您的IDE应该为您这样做——当您键入"override gethashcode"时,IDE应该生成这个样板代码。Visual Studio不执行此操作,但SharpDevelop执行此操作。
- GetHashCode方法的默认实现不保证不同对象的唯一返回值。因此,不能将此方法的默认实现用作哈希目的的唯一对象标识符。发件人:msdn.microsoft.com/en-us/library/system.object.gethashcode.a‌&8203;spx
- 在vs中,必须使用equals片段
- @大脑-我读过这个。这是否意味着当要将对象存储在字典中时,应始终重写GetHashCode?我不这么认为-几乎没有人这样做。对于字典来说,默认实现工作正常。它并不完美,但很好:stackoverflow.com/questions/750947/net unique object identif‌&8203;ier
通常,我使用类的组件属性中的聚合GetHashCode。例如。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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;
}
} |
- 这不是一个很好的方法,请参见stackoverflow.com/questions/263400/…
- 一般来说,添加不利于创建复合哈希代码。但在这个具体的例子中,我认为它没有问题。但是,当然,在不重写equals的情况下重写gethashcode没有多大意义。
- 好吧,你每天都要学点东西!