Luke Luke - 9 months ago 44
C# Question

Dictionary throwing StackOverflowException after ContainsKey for an object is called

The following code is part of a heavily object orientated C# script, where I received the error:

An unhandled exception of type 'System.StackOverflowException' occurred in script.exe


I found this to be particularly odd, since I couldn't find anything that could possibly relate to some form of process infinitely occurring within the logic of my program.

It would consistently happen as a part of
operator !=
I had made for a Coordinates class, whenever it was used as a parameter for a
Dictionary.ContainsKey()
that should have returned
true
.

This is the Coordinate Class:

class Coordinate
{
private int _x;
private int _y;
public int X
{
get
{
return _x;
}
}
public int Y
{
get
{
return _y;
}
}

public Coordinate(Random r)
{
this._x = r.Next(79);
this._y = r.Next(24);
}

public Coordinate(int x, int y)
{
this._x = x;
this._y = y;
}

public static Coordinate operator +(Coordinate a, Coordinate b)
{
return new Coordinate(a.X + b.X, a.Y + b.Y);
}

public static bool operator ==(Coordinate a, Coordinate b)
{
return ((a != null && b != null) && (a.X == b.X && a.Y == b.Y)) || (a == null && b == null);
}

public static bool operator !=(Coordinate a, Coordinate b)
{
return a != null && b != null && (a.X != b.X || a.Y != b.Y) || (a == null && b != null) || (a != null && b == null);
}

public override int GetHashCode()
{
return this.X.GetHashCode() * 23 + this.Y.GetHashCode() * 17;
}

public override bool Equals(object obj)
{
Coordinate other = obj as Coordinate;
return other != null && other.X == this.X && other.Y == this.Y;
}
}


This is the code that would consistently cause the error, whenever the
_positions.ContainsKey(position)
should have returned
true
:

private bool OutOfRangeCheck(Coordinate position)
{
return position.X < 1 || position.X > 10 || position.Y < 1 || position.Y > 10;
}

private bool PositionConflictCheck(Coordinate position)
{
bool temp = _positions.ContainsKey(position);
return OutOfRangeCheck(position) || _positions.ContainsKey(position);
}


The goal of this part of the program, was to see if a particular Coordinate had a counterpart with equal X and Y values in the dictionary shown. I found that this wouldn't work unless I had overridden the
GetHashCode()
and
Equals()
methods.

If it helps, when looking at the local variables upon the error being thrown, the 'a' Coordinate in the
operator !=(Coordinate a, Coordinate b)
method, was listed as
Unable to read memory
and had a red X next to it.

Any help would be greatly appreciated.

Answer Source

You are overriding the equals operator (==) and using the equals operator in there.

a != null && b != null

If you want to compare to null, without it using your operator either cast it to an object first, like (object)a != null or use object.ReferenceEquals(a, null).

This also applies for your not equals operator, even though it's not used by Dictionary.ContainsKey.