2011-09-05 72 views
10

嗨,我有一个具有6个字符串属性的类。一个独特的对象对于这些字段中的至少一个将具有不同的值C#.NET GetHashCode函数问题

要实现IEqualityComparer的GetHashCode函数,我将连接所有6个属性并在结果字符串上调用GetHashCode。

我有以下疑点:

  1. 是否需要调用GetHashCode的一个独特的价值?
  2. 对六个属性的连接操作是否会使比较变慢?
  3. 我应该使用其他方法吗?
+0

是你计划比较你的对象在某个地方,比如在一个数组中排序它们?这将改变是否你需要实现GetHashCode – mydogisbox

+0

嗨mydogisbox,我用它的List.Contains方法并将比较对象传递给它。我已经实现了Equals,并且不知道GetHashcode的正确方法 – ganeshran

回答

3

GetHashCode并不需要返回的“不平等”的对象不等价。它只需要为相等的对象返回相等的值(它也必须在对象的生命周期内返回相同的值)。

这意味着:

  1. 如果两个对象比较Equals为相等,那么他们必须GetHashCode返回相同的值。
  2. 如果某些字符串6个属性没有严格只读的,他们不能把在GetHashCode实现部分。

如果你不能同时满足这两点,那么你应该重新评估你的设计,因为其他任何事情都会为漏洞开放。

最后,您可以通过在6个字符串的每一个上调用GetHashCode,然后使用一些按位操作将所有6个结果集成一个值,使得GetHashCode速度更快。

+0

嗨乔恩,我的任何属性都是只读的。但是,它们都有私人设置器,所以只能从构造器中进行修改。这会影响他们在GetHashCode中的使用吗? – ganeshran

+0

@ ganeshran:那么它们在对象的整个生命周期内是有效的只读(即,如果你愿意,它们可以用'readonly'后台字段来实现),这就足够了。你会没事的。 – Jon

+0

@Jon读取你的GetHashCode()实现的条件,我发现它是一个需求冲突的问题。事实上,你只是部分正确。 GetHashCode()方法的实际要求是: 1.它应该为相等的对象返回相同的值。 2.对于同一个对象,当它没有被修改时,它应该返回相同的值。 3. GetHashCode()应该很快。 同意,还有一些其他建议。例如这一个:为了获得最佳性能,散列函数应该为所有输入生成一个随机分布。 –

3

如果您在这些对象上调用Equals(),则GetHashCode()应该为所有返回true的对象返回相同的哈希码。这意味着,例如,无论字段值是什么,您都可以返回零作为散列码。但是,如果存储在哈希表等数据结构中,这会使对象非常低效。

结合弦是一种选择,但请注意,例如,您可以结合只是stringsfor的哈希码(同时仍然处于比较平等的所有字符串!)两种。

您也可以结合六个单独字符串的哈希值,而不是计算一个散列组合的字符串。看例如 Quick and Simple Hash Code Combinations

我不知道这是否会比连接字符串显着更快。

+0

谢谢Anders,我仅将它用于Contains方法比较。如果我只为散列码组合两个字符串,如果对象中的两个值是相同的,那么这些散列码是不会相同的?这会混淆比较,还是GetHashCode对比较本身没有影响,并且只会影响性能 – ganeshran

+1

其他人已经提出这一点,但我想用不同的方式来解决它,因为它看起来是你的直觉卡住。注意到GetHashCode()返回一个int,它只能取得2^32个不同的值。你的对象由6个任意长度的字符串组成,显然可以带有大量的值。通过这个例子,我们可以很容易地看到GetHashCode()不可能是对象的所有可能值的唯一值。它只能满足这个属性:“if a.Equals(b)then a.GetHashCode()== b.GetHashCode()”;并注意到“如果”不能双向进行。 –

+1

GetHashCode()的实际考虑因素是“好”和“快”。为了使它“快”,我会尽量避免所有的内存分配和字符串复制;使它“好”是一个细微差别的主题,但在实践中,像@Jon所建议的那样,将子对象的GetHashCode()值混合在一起就足够了。我将发布ReSharper的建议作为“答案”,以便我可以获取代码格式。 –

4

如果字符串字段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; 
    } 
} 
+0

谢谢,我将使用此代码。 – ganeshran

+0

在这里看到我的答案:http://stackoverflow.com/a/34006336/1911540 –