1

I have the following class:

public class Foo
{
    public Guid Id { get; set; }
    public string Bar { get; set; }
    public DateTime Baz { get; set; }
}

And I want to test it for equality in a Dictionary like so:

var dict = new Dictionary<Guid, Foo>();
// Add some foos...
if (dict.ContainsValue(myFoo))
{
    // Do something...
}

Where ContainsValue should return true for Foos where the Bar and Baz properties are equal to one already in the dictionary.

The ContainsValue documentation states that the default EqualityComparer is used. This suggests that I can implement the IEquatable interface and override the default Equals implementation like so:

public override bool Equals(Foo obj)
{
        return obj != null &&
               Id.Equals(obj.Id) &&
               Bar == obj.Bar &&
               Baz == obj.Baz;
}

This blog post from MSDN suggests that when implementing IEquatable, one must also override the Equals(object) and GetHashCode() functions.

However, if I were to use the same Equality logic for the Equals and GetHashCode functions, the object's hashcode would be based on mutable fields which is recommended against in this StackOverflow answer.

So therefore, my question:

How should we define equality logic for mutable objects in cases like the one shown above whilst avoiding the problems inherent in basing an object's hashcode on mutable values?

  • 2
    You should not be searching for values in a dictionary. It's a sign that your data is improperly structured, as that's not an efficient query to perform. If you need to be searching for values of that type, then it should either be in a set, or be the key of a dictionary. That, or you should be figuring out how to search for records by their GUID, rather than by the value. – Servy Jan 22 '19 at 16:18
  • 1
    @Servy, would agree, but I don't think that is the context of the question. This question is likely related to checking if an object with duplicate data exists already, perhaps the key is generated internally and the rest of the data comes from an external source. It would seem there is a mismatch between needing to override GetHashCode and only being able to tell if an object is equal based on its mutable properties. – Mr Shoubs Jan 22 '19 at 16:47
  • @MrShoubs If they regularly need to check if an item with the same data already exists then, as I said, *they should be storing that data differently* so that they can more efficiently search for existing records. Doing a linear search through the data for duplicates is a poor idea unless it happens very rarely. Given that the data needs to be redesigned, the problem that they're facing with a design that they shouldn't be using isn't really important. – Servy Jan 22 '19 at 16:54
  • 1
    @Servy In this case, my dictionary is generally used for lookups via the keys and the number of items contained in it is small. However, on the rare occasion that something does get added, it would not be possible to use the key to determine if the item is there. – Nathan Jones Jan 22 '19 at 17:27

0 Answers0