HashSet does not delete object

I may have missed something using HashSet and HashCode, but I don't know why it doesn't work as I thought. I have an object with a HashCode that is being overridden. I added an object to the HashSet and later I change the property (which is used to calculate the HashCode) then I cannot delete the object.

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


source to share


3 answers


First, you are overriding GetHashCode

, but not overriding Equals

. Do not do this. They must always be redefined at the same time, sequentially.

Then you are correct that changing the hashcode of the objects will affect its lookup in any hash data structures. In the end, the first part of checking for a key in a hash structure is to find equal candidate values ​​by quickly finding all existing entries with the same hash code. There is no way for the data structure to "know" that the hash code has changed and updated its own view.



The documentation makes it clear:

You can override GetHashCode

for immutable reference types. In general, for mutable reference types, you should GetHashCode

only override if:

  • You can compute the hash code from fields that don't change; or
  • You can ensure that the hash code of the mutable object does not change as long as the object is contained in a collection that relies on its hash code.
+7


source


HashCode is used to find an object in HashSet

/ Dictionary

. If the hash code with the changed object is no longer found in HashSet

, because when looking for a new HashSet, the bucket for items with that new hash code will (most likely) not contain the object (which is in the bucket marked with the old hash code).

Note that after the initial lookup the hashcode Equals

will be used to do the final match, but it does not apply to your particular case as you have the same object, and use the default equal values ​​to compare references.



Detailed Explanation / Recommendations - Recommendations and rules for GetHashCode by Eric Lippert .

0


source


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
}

      

first set the value to the Test object and then add it to the HashSet.

0


source







All Articles