HashSet不会删除对象

时间:2014-09-25 07:25:39

标签: c# hashset

可能我错过了使用HashSet和HashCode的东西,但我不知道为什么这不起作用。我有一个覆盖HashCode的对象。我将对象添加到HashSet,然后我更改了一个属性(用于计算HashCode),然后我无法删除该对象。

public class Test 
{
    public string Code { get; set; }
    public override int GetHashCode()
    {
        return (Code==null)?0: Code.GetHashCode();
    }
}

public void TestFunction()
{
    var test = new Test();
    System.Collections.Generic.HashSet<Test> hashSet = new System.Collections.Generic.HashSet<Test>();
    hashSet.Add(test);
    test.Code = "Change";

    hashSet.Remove(test);  //this doesn´t remove from the hashset
}

3 个答案:

答案 0 :(得分:8)

首先,您要覆盖GetHashCode但不会覆盖Equals。不要这样做。它们应始终以一致的方式同时被覆盖。

接下来,您是正确的,更改对象哈希码影响在任何基于哈希的数据结构中查找它。毕竟,检查基于散列的结构中是否存在密钥的第一部分是通过快速查找具有相同散列码的所有现有条目来找到候选相等的值。数据结构无法知道&#34;哈希码已被更改并更新其自己的表示。

documentation说明了这一点:

  

您可以为不可变引用类型覆盖GetHashCode。通常,对于可变引用类型,只有在以下情况下才应覆盖GetHashCode

     
      
  • 您可以从不可变的字段计算哈希码;或
  •   
  • 当对象包含在依赖于其哈希码的集合中时,您可以确保可变对象的哈希码不会更改。
  •   

答案 1 :(得分:1)

public void TestFunction()
{
    var test = new Test();
    System.Collections.Generic.HashSet<Test> hashSet = new System.Collections.Generic.HashSet<Test>();
    test.Code = "Change";
    hashSet.Add(test);

    hashSet.Remove(test);  //this doesn´t remove from the hashset
}

首先将值设置为Test的对象,然后将其添加到HashSet。

答案 2 :(得分:0)

HashCode用于在HashSet / Dictionary中查找对象。如果在HashSet中找不到哈希代码更改对象,因为当查找新哈希集时,具有该新哈希代码的项目的桶将不会(很可能)包含该对象(在标记为旧的桶中)哈希码)。

请注意,在使用哈希代码Equals进行初始搜索后,将使用最终匹配,但它不适用于您的特定情况,因为您具有相同的对象并使用比较引用的默认Equals。

详细说明/指南 - Guidelines and rules for GetHashCode Eric Lippert