[英]C# Using Equals method in a generic list fails
I have a project where I have class State which uses templates. 我有一个项目,我有类State使用模板。 I have a class Cell, and I use it as State, so State holds a Cell as genericState.
我有一个类Cell,我用它作为State,所以State将一个Cell作为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.
问题是,它永远不会将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
}
and code of Class Cell, in which it never gets: 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;
}
}
I don't understand why it never gets to Equal method of Cell. 我不明白为什么它永远不会达到Cell的Equal方法。 What could be wrong with the code?
代码有什么问题?
The problem is that your code does not know that T
has a special method 问题是你的代码不知道
T
有一个特殊的方法
bool Equals<T>(T other)
It thinks that it should be calling Cell
's override of Equals(object)
, which your code does not override. 它认为它应该调用
Cell
的Equals(object)
覆盖,你的代码不会覆盖它。
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>
: 固定,这是简单的:添加
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
}
Firstly, you should override object.Equals
to defer to this Equals
: 首先,您应该覆盖
object.Equals
以遵循此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()
: 如果你要重写
object.Equals
,那么你还需要重写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
. 除此之外,为了获得更好的性能,您可以让
Cell
实现IEquatable<Cell>
,并在您的State<T>.Equals
使用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. 这样会更好,因为
EqualityComparer<T>.Default
在实现时使用IEquatable<T>.Equals(T)
,当它不可用时回IEquatable<T>.Equals(T)
object.Equals(object)
。
genericState.Equals
is the equality method derived from object
. genericState.Equals
是从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. 在您的
Cell
类中,您没有覆盖object.Equals(object)
,因此不会调用您的相等方法( Cell.Equals(Cell)
),而是调用Cell.Equals(object)
。 So what you can do to fix this is change your Cell
class to override the default equality method: 那么你可以做些什么来解决这个问题就是改变你的
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.