4

I have HashSet of my custom class:

public class Vertex
{
    public string Name;

    public override bool Equals(object obj)
    {
        var vert = obj as Vertex;
        if (vert !=null)
        {
            return Name.Equals(vert.Name, StringComparison.InvariantCulture);
        }
        return false;
    }
}

And now I have tow hashsets

HashSet<Vertex> hashSet1 = new HashSet<Vertex>();

HashSet<Vertex> hashSet1 = new HashSet<Vertex>();

And now I'd like to have in hashSet1 only Vertexes that are not in hashSet2 So I use ExceptWith method

hashSet1.ExceptWith(hashSet2);

But this doesn't work. I suppose that this doesn't work because I have complex type. So the question is: is there some interface required to be implemented in Vertex class to make this thing work? I know that while creation of HashSet I can pass a EqualityComparer but it seems to me that it would be more elegant to implement some comparing interface method in Vertex class.

Is it possible or I just doesn't understand sth?

Thanks.

steavy
  • 1,483
  • 6
  • 19
  • 42

4 Answers4

4

When overriding Equals you should also override GetHashCode. HashSet (and other hashing structures like Dictionary) will first calculate a hash code for your objects to locate them in tne structure before comparing elements with Equals.

public override int GetHashCode()
{
    return StringComparer.InvariantCulture.GetHashCode(this.Name);
}
Lee
  • 142,018
  • 20
  • 234
  • 287
3

You don't have to implement any interface (although IEquatable<T>) is encouraged. When you create a hash-set without specifying an equality-comparer, it defaults to using EqualityComparer<T>.Default, which asks the objects themselves to compare themselves to each other (special-casing null references).

However, in your case, your equality contract is broken since you haven't overriden GetHashCode. Here's how I would fix your type:

public class Vertex : IEquatable<Vertex>
{
    public string Name { get; private set; }

    public Vertex(string name)
    {
        Name = name;
    }

    public override int GetHashCode()
    {
        return StringComparer.InvariantCulture.GetHashCode(Name);
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Vertex);
    }

    public bool Equals(Vertex obj)
    {
        return obj != null && StringComparer.InvariantCulture.Equals(Name, obj.Name);
    }
}
Ani
  • 111,048
  • 26
  • 262
  • 307
1

Would you mind overriding the .GetHashCode()too?

Here's the reference.

Community
  • 1
  • 1
Freddie Fabregas
  • 1,162
  • 1
  • 7
  • 17
0

You have to override GetHashCode with Equals overriding.

Object.Equals Method:

Types that override Equals(Object) must also override GetHashCode; otherwise, hash tables might not work correctly.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263