【问题标题】:Contains() returns false even though it should return trueContains() 会返回 false,即使它应该返回 true
【发布时间】:2013-05-08 09:49:21
【问题描述】:

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

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

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

但是即使我可以肯定在调试时看到我想要的 Move 在 *m_EatingMove* 列表中,表达式也会返回 false,我认为问题可能是我没有在我的结构中覆盖了 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

【问题讨论】:

  • 你是否也为Move实现了Equals
  • 你的结构是可变的,即generally inadvisable
  • @EvanTrimboli,既然你提到了它,我实现了 Equal 而不是 Equals 移动,但是我应该在签名中使用覆盖词吗?

标签: c#


【解决方案1】:

您还需要重写GetHashCode 方法,以便两个相等的单元格返回相同的哈希码。一种经常使用的模式是对要比较的项目的哈希码进行异或运算,例如:

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

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

【讨论】:

    【解决方案2】:

    您必须为GetHashCode()Equals() 提供覆盖。要么,要么实现IEquatable&lt;T&gt;

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

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

    【讨论】:

    • List&lt;T&gt; 类的实际成员名为Contains,这意味着不应考虑 LINQ 版本。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      通常,List&lt;T&gt;.Contains 是使用EqualityComparer&lt;T&gt; 比较元素的通用方法。在你的情况下,它调用Object.Equals,你可以覆盖Object.Equals

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-14
        • 2011-01-18
        • 2020-07-18
        • 1970-01-01
        • 2019-03-29
        • 2014-10-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多