Question

I need to define hashset which key is MyClass

public class MyClass
{
    private string m_x;
    private string m_y;
    MyClass(string x,string y)
    {
       m_x = x;
       m_y =y;
    }
}

So I have

HashSet <MyClass> myHash;
MyClass m = new MyClass("1","123");
myHash.Add(m);
bool isContained = myHash.Contains(m);

IsContained is false....What is wrong? what could be another container, which allows to save the unique keys? and return the answer if key is inside with minimum complexity?

Was it helpful?

Solution

a) Assuming you don't want to compare the objects by their references, you should override GetHashCode and Equals methods of MyClass

HashSet<MyClass> myHash = new HashSet<MyClass>();
MyClass m1 = new MyClass("1", "123");
MyClass m2 = new MyClass("1", "123");
myHash.Add(m1);
bool b = myHash.Contains(m2); //true

public class MyClass
{
    private string m_x;
    private string m_y;
    public MyClass(string x, string y)
    {
        m_x = x;
        m_y = y;
    }

    public override int GetHashCode()
    {
        return m_x.GetHashCode() ^ m_y.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(this, obj)) return true;
        if (obj == null) return false;
        var other = obj as MyClass;
        return m_x == other.m_x && m_y == other.m_y;
    }
}

b) You can also use IEqualityComparer to compare your objects, But in this case you need some public properties

public class MyClass
{
    public string m_x;
    public string m_y;
    public MyClass(string x, string y)
    {
        m_x = x;
        m_y = y;
    }
}

public class MyEqualityComparer : IEqualityComparer<MyClass>
{

    public bool Equals(MyClass x, MyClass y)
    {
        return x.m_x == y.m_x && x.m_y == y.m_y;
    }

    public int GetHashCode(MyClass obj)
    {
        return obj.m_x.GetHashCode() ^ obj.m_y.GetHashCode();
    }
}

Now, you only need to give the comparer to the HashSet's constructor

HashSet<MyClass> myHash = new HashSet<MyClass>( new MyEqualityComparer());

OTHER TIPS

Just change your MyClass so it implements Equals and GetHashCode:

public class MyClass
{
    private string m_x;
    private string m_y;

    public MyClass(string x, string y)
    {
        m_x = x;
        m_y = y;
    }

    public override bool Equals(object obj)
    {
        var typed = obj as MyClass;
        if (typed == null) return false;
        return typed.m_x == m_x && typed.m_y ==m_y;
    }

    public override int GetHashCode()
    {
        return new {m_x, m_y}.GetHashCode();
    }
}

Now the IsContained2 also is true, even if it has not been added to the HashSet:

HashSet<MyClass> myHash =new HashSet<MyClass>();
MyClass m = new MyClass("1", "123");
MyClass m2 = new MyClass("1", "123");
myHash.Add(m);
bool isContained = myHash.Contains(m);
bool isContained2 = myHash.Contains(m2); // True!
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top