嗨,我有一个具有6个字符串属性的类。一个独特的对象对于这些字段中的至少一个将具有不同的值C#.NET GetHashCode函数问题
要实现IEqualityComparer的GetHashCode函数,我将连接所有6个属性并在结果字符串上调用GetHashCode。
我有以下疑点:
- 是否需要调用GetHashCode的一个独特的价值?
- 对六个属性的连接操作是否会使比较变慢?
- 我应该使用其他方法吗?
嗨,我有一个具有6个字符串属性的类。一个独特的对象对于这些字段中的至少一个将具有不同的值C#.NET GetHashCode函数问题
要实现IEqualityComparer的GetHashCode函数,我将连接所有6个属性并在结果字符串上调用GetHashCode。
我有以下疑点:
GetHashCode
并不需要返回的“不平等”的对象不等价。它只需要为相等的对象返回相等的值(它也必须在对象的生命周期内返回相同的值)。
这意味着:
Equals
为相等,那么他们必须GetHashCode
返回相同的值。GetHashCode
实现部分。如果你不能同时满足这两点,那么你应该重新评估你的设计,因为其他任何事情都会为漏洞开放。
最后,您可以通过在6个字符串的每一个上调用GetHashCode
,然后使用一些按位操作将所有6个结果集成一个值,使得GetHashCode
速度更快。
嗨乔恩,我的任何属性都是只读的。但是,它们都有私人设置器,所以只能从构造器中进行修改。这会影响他们在GetHashCode中的使用吗? – ganeshran
@ ganeshran:那么它们在对象的整个生命周期内是有效的只读(即,如果你愿意,它们可以用'readonly'后台字段来实现),这就足够了。你会没事的。 – Jon
@Jon读取你的GetHashCode()实现的条件,我发现它是一个需求冲突的问题。事实上,你只是部分正确。 GetHashCode()方法的实际要求是: 1.它应该为相等的对象返回相同的值。 2.对于同一个对象,当它没有被修改时,它应该返回相同的值。 3. GetHashCode()应该很快。 同意,还有一些其他建议。例如这一个:为了获得最佳性能,散列函数应该为所有输入生成一个随机分布。 –
如果您在这些对象上调用Equals(),则GetHashCode()应该为所有返回true的对象返回相同的哈希码。这意味着,例如,无论字段值是什么,您都可以返回零作为散列码。但是,如果存储在哈希表等数据结构中,这会使对象非常低效。
结合弦是一种选择,但请注意,例如,您可以结合只是stringsfor的哈希码(同时仍然处于比较平等的所有字符串!)两种。
您也可以结合六个单独字符串的哈希值,而不是计算一个散列组合的字符串。看例如 Quick and Simple Hash Code Combinations
我不知道这是否会比连接字符串显着更快。
谢谢Anders,我仅将它用于Contains方法比较。如果我只为散列码组合两个字符串,如果对象中的两个值是相同的,那么这些散列码是不会相同的?这会混淆比较,还是GetHashCode对比较本身没有影响,并且只会影响性能 – ganeshran
其他人已经提出这一点,但我想用不同的方式来解决它,因为它看起来是你的直觉卡住。注意到GetHashCode()返回一个int,它只能取得2^32个不同的值。你的对象由6个任意长度的字符串组成,显然可以带有大量的值。通过这个例子,我们可以很容易地看到GetHashCode()不可能是对象的所有可能值的唯一值。它只能满足这个属性:“if a.Equals(b)then a.GetHashCode()== b.GetHashCode()”;并注意到“如果”不能双向进行。 –
GetHashCode()的实际考虑因素是“好”和“快”。为了使它“快”,我会尽量避免所有的内存分配和字符串复制;使它“好”是一个细微差别的主题,但在实践中,像@Jon所建议的那样,将子对象的GetHashCode()值混合在一起就足够了。我将发布ReSharper的建议作为“答案”,以便我可以获取代码格式。 –
如果字符串字段AF命名,并已知不为空,这是ReSharper的建议,为您的GetHashCode()
public override int GetHashCode() {
unchecked {
int result=a.GetHashCode();
result=(result*397)^b.GetHashCode();
result=(result*397)^c.GetHashCode();
result=(result*397)^d.GetHashCode();
result=(result*397)^e.GetHashCode();
result=(result*397)^f.GetHashCode();
return result;
}
}
谢谢,我将使用此代码。 – ganeshran
在这里看到我的答案:http://stackoverflow.com/a/34006336/1911540 –
是你计划比较你的对象在某个地方,比如在一个数组中排序它们?这将改变是否你需要实现GetHashCode – mydogisbox
嗨mydogisbox,我用它的List.Contains方法并将比较对象传递给它。我已经实现了Equals,并且不知道GetHashcode的正确方法 – ganeshran