views:

204

answers:

2
+1  Q: 

C# Queue problem

Suppose I have a class

XYNode
{
    protected int mX;
    protected int mY;
}

and a queue

Queue<XyNode> testQueue = new Queue<XYNode>();

I want to check if a node with that specific x and y coordinate is already in the queue. The following obviously doesn't work :

testQueue.Contains(new XYNode(testX, testY))

because even if a node with those coordinates is in the queue, we're testing against a different XYNode object so it will always return false.

What's the right solution ?

+18  A: 

The simplest way is to override Equals so that one XYNode knows whether it's equal to another XYNode. You should override GetHashCode() at the same time, and possibly also implement IEquatable<XYNode> to allow a strongly-typed equality comparison.

Alternatively, you could write an IEqualityComparer<XYNode> implementation to compare any two nodes and return whether or not they're the same - and then pass that into the call to the appropriate overload of the Contains extension method defined in Enumerable (assuming you're using .NET 3.5).

Further things to consider:

  • Could you use private fields instead of protected ones?
  • Could your class be sealed?
  • Could your class be immutable?
  • Should your class perhaps be a struct instead? (Judgement call...)
  • Should you overload the == and != operators?
Jon Skeet
pretty soon you're going to win stackoverflow.com
scottm
+1 For the partial answer with ghost improvement.
ChaosPandion
"FIRST"? ghost?
astander
anyway good answer!!!
astander
I think Jon is trying to get enough points to turn this site into "BufferOverflow.com"
Matthew Whited
+6  A: 

To illustrate Jon Skeet's ... original ... answer:

class XYNode {
    protected int mX;
    protected int mY;

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

        XYNode otherNode = (XYNode)obj;
        return (this.mX == other.mX) && (this.mY == other.mY);
    }
}

This is a pretty simplistic solution. There are a lot of additional factors to consider, which Jon has already mentioned.

Dan Tao
You need to specify override and the parameter should be an object.
ChaosPandion
@ChaosPandion: Thanks.
Dan Tao
One handy thing about making a class sealed is that you can just use as/is instead of calling `GetType()` - you don't need to worry about being given a subclass instance.
Jon Skeet