HashSet allows duplicate item insertion - C#

I'm guessing that you are creating a new Quotes with the same values. In this case they are not equal. If they should be considered equal, override the Equals and GetHashCode methods.

public class Quotes{ 
    public string symbol; 
    public string extension

    public override bool Equals(object obj)
    {
        Quotes q = obj as Quotes;
        return q != null && q.symbol == this.symbol && q.extension == this.Extension;
    }

    public override int GetHashCode()
    {
        return this.symbol.GetHashCode() ^ this.extension.GetHashCode();
    }
}

I had thought that when calling values.Add(new Quotes(symb, ext)); with the same symb and ext, 'false' would be returned and the element would not be added.

This is not the case.

HashSet will use GetHashCode and Equals to determine equality of your objects. Right now, since you're not overriding these methods in Quotes, the default System.Object's reference equality will be used. Each time you add a new Quote, it's a unique object instance, so the HashSet sees it as a unique object.

If you override Object.Equals and Object.GetHashCode, it will work as you expect.


HashSets first compare entries based on their hash which is calculated by GetHashCode.
The default implementation returns a hashcode based on the object itself (differs between each instance).

Only if the hashes are the same (very improbable for hashes based on instances), the Equals method is called and used to definitely compare two objects.

You have to options:

  • Change Quotes to a struct
  • Override GetHashCode and Equals in Quotes

Example:

 public override int GetHashCode()
 {
    return (this.symbol == null ? 0 : this.symbol.GetHashCode())
       ^ (this.extension == null ? 0 : this.extension.GetHashCode());
 }
 public override bool Equals(object obj)
 {
    if (Object.ReferenceEquals(this, obj))
      return true;

    Quotes other = obj as Quotes;
    if (Object.ReferenceEquals(other, null))
      return false;

    return String.Equals(obj.symbol, this.symbol)
        && String.Equals(obj.extension, this.extension);
 }

Tags:

C#

.Net

Hashset