我有一个项目,其中我有使用模板的类State。 我有一个类Cell,我用它作为State,所以State将一个Cell作为genericState。 现在我有一个通用函数,它检查两个实例是否相等。 问题是,它永远不会将State Equals方法留给Cell Equals方法。
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
}
和Class Cell的代码,它永远不会得到:
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;
}
}
我不明白为什么它永远不会得到Cell的Equal方法。代码有什么问题?
答案 0 :(得分:2)
问题是您的代码不知道T
有特殊方法
bool Equals<T>(T other)
它认为它应该调用Cell
覆盖Equals(object)
,而您的代码不会覆盖。
解决这个问题很简单:将IEquatable<Cell>
添加到Cell
实现的接口列表中,并在T
上添加约束以确保它实现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
}
答案 1 :(得分:1)
首先,您应该覆盖object.Equals
以遵循此Equals
:
public override bool Equals(object obj) => Equals(obj as Cell);
如果您要覆盖object.Equals
,那么您还需要覆盖object.GetHashCode()
:
public override int GetHashCode() => row * 31 + col;
除此之外,为了获得更好的效果,您可以Cell
实施IEquatable<Cell>
,并State<T>.Equals
使用EqualityComparer<T>.Default
。这样做会更好,因为EqualityComparer<T>.Default
在实施时会使用IEquatable<T>.Equals(T)
,而在object.Equals(object)
不可用时会回退到{{1}}。
答案 2 :(得分:0)
genericState.Equals
是从object
派生的等式方法。在Cell
类中,您没有覆盖object.Equals(object)
,因此未调用您的相等方法(Cell.Equals(Cell)
),而是调用Cell.Equals(object)
。因此,您可以采取的措施是更改Cell
类以覆盖默认的相等方法:
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;
}
}