Reputation: 13
I have a struct IntVector2 which has an X and Y property. The + operator is overridden with
public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
return value1;
}
When using this in a List with the contains method, it's not checking the total value of the addition, but just the variable "current"
if (visited.Contains(current + dir))
continue;
What's actually going on here?
Edit: Here's a screenshot of the values of the variables, and a variable declaration that equals what I'm expecting the value of the contains to check.
https://dl.dropboxusercontent.com/u/30062610/Brokestuff.png
Edit2: Here's the full code of the method, it's the start of an A* Pathfinding algorithm finding the end vector from the start vector.
public Path Pathfind(IntVector2 start, IntVector2 end)
{
Queue<IntVector2> fillQueue = new Queue<IntVector2>();
List<IntVector2> visited = new List<IntVector2>();
fillQueue.Enqueue(start);
IntVector2 current;
while (fillQueue.Count > 0)
{
current = fillQueue.Dequeue();
foreach (IntVector2 dir in Directions)
{
if (GetCell(current + dir).IsWall)
continue;
else
{
IntVector2 newstuff = current + dir;
if (visited.Contains(current + dir))
continue;
if ((current + dir) == end)
{
//We've reached the target, traceback the path and return it.
}
visited.Add(current);
fillQueue.Enqueue(current + dir);
}
}
}
return null;
}
Edit 3: Even using the newstuff variable which has a different value from the start hits the continue. I'm not sure what it could be doing. My equals override just checks if X and Y are both equal and returns true if so.
Here's the entirety of the IntVector2 code: http://pastebin.com/ic108SeF
Edit 4: I modified the + operator to:
public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
{
return new IntVector2((value1.X + value2.X), (value1.Y + value2.Y));
}
And the problem still persists.
Upvotes: 1
Views: 697
Reputation: 5357
Ok, I believe I figured out your problem.
Your equals override isn't an override, you have it in your code as:
public bool Equals(IntVector2 other) {
return (X == other.X) && (Y == other.Y);
}
What you did there was added a Method called Equals. So you have in effect overloaded the Actual equals method you need to override. Contains won't call your equals method, because it calls the original one that takes an object.
And when you override the right equals method you should, in good practice, implement GetHashCode and use GetHashCode to determine if the objects are truly equal.
In your case you won't have an issue not overriding GetHashCode, as you are basing eqaulity on two integers being the same in another copy of the IntVector2, and you can't really compute an integer hash code for that as X and Y are both integers. If you did a GetHashCode implementation here, you could run into bugs later if you have a large number of these you could end up with dupe hash codes that are non equal objects.
Here is the updated code you should try.
public struct IntVector2
{
public int X { get; set; }
public int Y { get; set; }
public static IntVector2 operator +(IntVector2 value1, IntVector2 value2)
{
value1.X += value2.X;
value1.Y += value2.Y;
return value1;
}
public override int GetHashCode()
{
//overrode this to get rid of warning
return base.GetHashCode();
}
//This equals get's called, notice the override keyword
public override bool Equals(object obj)
{
if (obj is IntVector2)
{
IntVector2 vObj = (IntVector2)obj;
return vObj.X == this.X && vObj.Y == this.Y;
}
return false;
}
//This won't get called, it's not part of the framework, this is adding a new overload for equals that .Net won't know about.
public bool Equals(IntVector2 other)
{
return (X == other.X) && (Y == other.Y);
}
public override string ToString()
{
return string.Format("{ value1: {0}, value2: {0} }", X, Y);
}
}
Upvotes: 1
Reputation: 55489
You have a typo in the Equals
method:
public override bool Equals(object obj)
{
if (obj is IntVector2)
{
return Equals((IntVector2)this); // <-- "this" should be "obj"
}
}
The erroneous code compares this
to this
, so it always returns true
.
Upvotes: 1
Reputation: 183
With your current code, Contains is unable to determine equality for two structure instances. If you override IntVector2::GetHashCode so that identical values return the same hash, it should start working as you expect.
Upvotes: -1