C#在通用列表中使用Equals方法失败

时间:2016-03-26 12:26:37

标签: c# templates generics equals

我有一个项目,其中我有使用模板的类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方法。代码有什么问题?

3 个答案:

答案 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;    
    }
 }