Contains()返回false,即使它应该返回true

时间:2013-05-08 01:07:18

标签: c#

我目前正在尝试检查我的某个列表是否包含一个对象。 该列表是一个对象的列表,该对象由包含2个字段的结构组成。

我正在尝试运行这个小代码:

if(m_EatingMoves.Contains(i_Move))
{
  ....
}

但是表达式将返回false,即使我可以肯定在调试中看到Move我想要的是在* m_EatingMove *列表中,我认为问题可能是我没有在我的struct中重写了Equals,所以我在StackOverFlow上找到了一个实现,但表达式仍然返回false。除了实现我自己的Contains()之外的任何想法?

这是结构:

    public struct Cell
    {
        public int Row;
        public int Col;

        public Cell(int i_Row, int i_Col)
        {
            this.Row = i_Row;
            this.Col = i_Col;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Cell))
                return false;

            Cell cell = (Cell)obj;
            return cell.Col == Col && cell.Row == Row;
        }
    }

现在我有另一个由上面的结构组成的对象:

    public class Move
    {
        private Board.Cell m_Source;
        private Board.Cell m_Destination;

        public Move(Board.Cell i_Source, Board.Cell i_Destination)
        {
            m_Source = i_Source;
            m_Destination = i_Destination;
        }
....(Properties, etc..)

最后,我们有了由构造函数

初始化的列表
private List<Move> m_EatingMoves

4 个答案:

答案 0 :(得分:3)

您必须为GetHashCode()以及Equals()提供覆盖。要么是,要么实施IEquatable<T>

Contains方法是Linq扩展,它使用默认的相等比较器。来自docs

  

Default属性检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer。否则,它返回一个EqualityComparer,它使用由T提供的Object.Equals和Object.GetHashCode的覆盖。

答案 1 :(得分:3)

您还需要覆盖GetHashCode方法,以便两个相等的单元格返回相同的哈希码。经常使用的模式是对要比较的项的哈希码进行xor,例如:

public struct Cell
{
   [...]
   public override int GetHashCode()
   {
       return Row.GetHashCode() ^ Col.GetHashCode();
   }
}

如果不重写此方法,数据结构可能无法正确比较相等性,从而导致您观察到的行为。 MSDN GetHashCode有关于如何在框架内使用此方法的其他文档。

答案 2 :(得分:1)

我建议不要使用简单类型(例如字符串)来比较对象/结构(有点难以预测的任务和潜在的多重副作用)来为对象添加一些唯一ID,并使用Contains()基于此ID。此外,struct是一种值类型,因此可能会导致装箱/拆箱的问题(可能是这种情况)。此致,AB

答案 3 :(得分:0)

通常,List<T>.Contains是使用EqualityComparer<T>比较元素的通用方法。在您的情况下,它会调用Object.Equals,您可以覆盖Object.Equals

您可以参考MSDN List(T).Contains Method