user2292539
user2292539

Reputation: 245

Custom dictionary key and subclass interaction

I am doing a custom dictionary key solution similar to whats described here: Use custom object as Dictionary Key

However in my case the key can be one of 2 objects in a hierarchy. I am getting the key not found exception when perfomring somethin like this:

foreach (IntPointMutable key in tmxMapOffsets.Keys)
{
     newTmxMapOffsets[new IntPoint(key.X - minXValue, key.Y + minYValue)] = tmxMapOffsets[key];
}

I considered the following scenarios for my 2 classes: IntPoint and IntPointMutable. They simply are 2 ints, X and Y wrapped in an object much like a vector2 is for floats.

I created a simple GetHashCode implementation that for my needs will produce all unique results(granted its not going to work if you had large values)

public override int GetHashCode()
{
    return x * 10000 + y;
}

I then implemented in IntPoint the following things

public class IntPoint:Object,IEquatable<IntPoint>,IEquatable<IntPointMutable>

public override bool Equals(Object obj)
{
    if (obj == null)
    {
        return false;
    }
    return (obj.GetType() == typeof(IntPoint) || obj.GetType() == typeof(IntPointMutable)) && (IntPoint)obj == this;
}

public bool Equals(IntPointMutable obj)
{
    if (obj == null)
    {
        return false;
    }
    return (IntPoint)obj == this;
}

public bool Equals(IntPoint obj)
{
    if (obj == null)
    {
        return false;
    }
    return obj.GetType() == typeof(IntPoint) && (IntPoint)obj == this;
}

So it seems like I have all my bases covered but yet it cannot do a dictionary lookup where one object of each type is involved. Also I dislike that I had to put knowledge of a subclass in its parent, but I wasn't sure how to allow an IntPoint.Equals(someIntPointMutable) situation to work otherwise.

Any ideas?

And also I overrode the == operator so that the comparison would work above

public static bool operator ==(IntPoint a, IntPoint b)
{
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    if((object)a == null ||(object)b == null)
    {
        return false;
    }

    // Return true if the fields match:
    return a.X == b.X && a.Y == b.Y;
}

Some updates after the various comments:

It apparently should work fine without knowing about the mutable version in the superclass as far as comparison checks go, so I will remove that. Also the mutable one was being stored into the dictionary which is a no-no so I changed that. Ideally I get rid of the mutable version to avoid this happening accidently. is the best bet to use a struct or something to replace this as an easy way to pass around a pair of ints thats more clear then just an int[]?

Upvotes: 0

Views: 167

Answers (1)

Shlomi Borovitz
Shlomi Borovitz

Reputation: 1700

What about implementing IntPoint as an immutable value type (if, indeed it contains no more than few fields), and discard MurableIntPoint?

Upvotes: 1

Related Questions