【问题标题】:C# Using Equals method in a generic list failsC# 在泛型列表中使用 Equals 方法失败
【发布时间】:2016-03-26 12:26:37
【问题描述】:

我有一个项目,其中有使用模板的 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
}

和单元格的代码,它永远不会得到:

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 方法。代码可能有什么问题?

【问题讨论】:

  • 我想this 可能会对你有所帮助

标签: c# templates generics equals


【解决方案1】:

问题是你的代码不知道T有一个特殊的方法

bool Equals<T>(T other)

它认为它应该调用CellEquals(object) 的覆盖,而您的代码没有覆盖它。

解决这个问题很简单:将IEquatable&lt;Cell&gt; 添加到Cell 实现的接口列表中,并在T 上添加一个约束以确保它实现IEquatable&lt;T&gt;

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】:

    首先,您应该覆盖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&lt;Cell&gt;,并在您的State&lt;T&gt;.Equals 中使用EqualityComparer&lt;T&gt;.Default。这会更好,因为EqualityComparer&lt;T&gt;.Default 在实现时使用IEquatable&lt;T&gt;.Equals(T),在不可用时回退到object.Equals(object)

    【讨论】:

    • 我应该把这段代码放在哪里?但是这样我就忽略了通用模板,不是吗?
    • 覆盖所有类型,可以在泛型模板中的编译类型处填充T,它会自动拾取
    • 哪个,EqualityComparer&lt;T&gt;.Default的使用?您使用EqualityComparer&lt;T&gt;.Default.Equals(genericState, (obj as State&lt;T&gt;).genericState) 而不是调用genericState.Equals((obj as State&lt;T&gt;).genericState)
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多