问题
I have a project where I have class State which uses templates. I have a class Cell, and I use it as State, so State holds a Cell as genericState. Now I have a generic function which checks if two instances are equal. Problem is, it never leaves the State Equals method to Cell Equals method.
public class State<T>
{
public T genericState; //in my case T is a cell
public State(T cellState) // CTOR
{
this.genericState = cellState;
}
public override bool Equals(object obj)
{
return genericState.Equals((obj as State<T>).genericState);
} //never leaves
}
and code of Class Cell, in which it never gets:
public class Cell
{
public int row, col;
public bool visited;
public char value;
public bool Equals(Cell other) //never gets here
{
return other != null && other.row == row && other.col == col;
}
}
I don't understand why it never gets to Equal method of Cell. What could be wrong with the code?
回答1:
The problem is that your code does not know that T
has a special method
bool Equals<T>(T other)
It thinks that it should be calling Cell
's override of Equals(object)
, which your code does not override.
Fixing this is simple: add IEquatable<Cell>
to the list of interfaces implemented by Cell
, and add a constraint on T
to ensure that it implements IEquatable<T>
:
public class State<T> where T : IEquatable<T> {
... // The rest of the code remains the same
}
...
public class Cell : IEquatable<Cell> {
... // The rest of the code remains the same
}
回答2:
Firstly, you should override object.Equals
to defer to this Equals
:
public override bool Equals(object obj) => Equals(obj as Cell);
And if you are overriding object.Equals
then you also need to override object.GetHashCode()
:
public override int GetHashCode() => row * 31 + col;
Further to this, for better performance you could have Cell
implement IEquatable<Cell>
, and in your State<T>.Equals
use EqualityComparer<T>.Default
. This will be better because EqualityComparer<T>.Default
uses IEquatable<T>.Equals(T)
when implemented, falling back to object.Equals(object)
when that isn't available.
回答3:
genericState.Equals
is the equality method derived from object
. In your Cell
class, you are not overriding object.Equals(object)
, so your equality method (Cell.Equals(Cell)
) is not being called, but instead, Cell.Equals(object)
is being called. So what you can do to fix this is change your Cell
class to override the default equality method:
public class Cell
{
public int row, col;
public bool visited;
public char value;
public override bool Equals(object other) //never gets here
{
if(!(other is Cell)) return false;
return other != null && other.row == row && other.col == col;
}
}
来源:https://stackoverflow.com/questions/36235271/c-sharp-using-equals-method-in-a-generic-list-fails