Strange behavior using structs with HashSet
Hello,
I've made the following struct to be used in a HashSet (the normal using System.Collections.Generic + System.Linq). It's struct rather than a class so when I make new stucts (as demonstrated below) so when I check equality and if the set contains it could pass items by value rather than by reference (which will always won't give me the result I need).
The struct:
public struct BoardCell
{
public int column;
public int row;
public int board;
public BoardCell(int c, int r, int b)
{
column = c;
row = r;
board = b;
}
public override bool Equals(object obj)
{
if (!(obj is BoardCell))
return false;
return (this.column == ((BoardCell)obj).column && this.row == ((BoardCell)obj).row && this.board == ((BoardCell)obj).board);
}
public static bool operator ==(BoardCell l, BoardCell r)
{
return (l.column == r.column && l.row == r.row && l.board == r.board);
}
public static bool operator !=(BoardCell l, BoardCell r)
{
return !(l == r);
}
public override int GetHashCode()
{
return (column * 10000 + row * 100 + board);
}
public static BoardCell GetReversed(BoardCell bc, int gridSize)
{
return new BoardCell(gridSize - bc.column - 1, gridSize - bc.board - 1, gridSize - bc.row - 1);
}
public static BoardCell GetInvalid()
{
return new BoardCell(-1, -1, -1);
}
public static bool IsValid(BoardCell bc)
{
return (bc.column != -1);
}
}
And the code that checks if an instance of this struct is in the set:
public void UpdateCell(int column, int row, int board, bool value)
{
gameBoard[column, row, board].OccupiedBy = value;
BoardCell bc = new BoardCell(column, row, board);
print(freeCells.Contains(bc));
if (!freeCells.Remove(bc))
Debug.LogError("duplicate?!");
LastCell = new BoardCell(column, row, board);
CheckWinner(column, row, board);
}
When I put prints in there there was something peculiar: The Remove method would ALWAYS return false as in the object is not in the set yet it did find it and remove it. The Contains method also returns false all the time. Now for what I know I didn't even had to override and implement equals, operator == and != and GetHashCode but since it didn't work right I've done it anyways and it still returns false upon check yet removes the correct struct from the set. Also it f***s up elsewhere where I query the set with Linq-SQL syntax, failing basic basic (if a.x == b.x return true) kind of stuff.
Is it a bug? Am I missing something? Using 5.4 and I've never had these kind of problems with 5.1 (the last time I've used Linq in Unity).
Best regards, Shay.
Share the rest of your code, there's nothing about a HashSet here.
Anyway these are part of the mono/C# infrastructure not part of Unity, I find it very hard to believe there's such a basic bug in those.