C#hashtable当我知道它有一个带密钥的条目时,ContainsKey返回false

时间:2012-09-07 16:25:56

标签: c# hashtable

 foreach (Ant ant in state.MyAnts)
        {
            if (m_foodTasks.ContainsKey(ant))
            {
...

通过调试我可以看到m_foodTasks中有一个具有完全相同值的蚂蚁。所以我会假设它比较参考地址..(我是对的吗?)

如何按价值进行比较?

阅读答案后编辑:

信息过多...... 我会花一点时间研究这些,但这里是蚂蚁已经拥有的东西(我不能说所有这些东西是什么):

public class Location : IEquatable<Location> {

    /// <summary>
    /// Gets the row of this location.
    /// </summary>
    public int Row { get; private set; }

    /// <summary>
    /// Gets the column of this location.
    /// </summary>
    public int Col { get; private set; }

    public Location (int row, int col) {
        this.Row = row;
        this.Col = col;
    }

    public override bool Equals (object obj) {
        if (ReferenceEquals (null, obj))
            return false;
        if (ReferenceEquals (this, obj))
            return true;
        if (obj.GetType() != typeof (Location))
            return false;

        return Equals ((Location) obj);
    }

    public bool Equals (Location other) {
        if (ReferenceEquals (null, other))
            return false;
        if (ReferenceEquals (this, other))
            return true;

        return other.Row == this.Row && other.Col == this.Col;
    }

    public override int GetHashCode()
    {
        unchecked {
            return (this.Row * 397) ^ this.Col;
        }
    }
}

public class TeamLocation : Location, IEquatable<TeamLocation> {
    /// <summary>
    /// Gets the team of this ant.
    /// </summary>
    public int Team { get; private set; }

    public TeamLocation (int row, int col, int team) : base (row, col) {
        this.Team = team;
    }

    public bool Equals(TeamLocation other) {
        return base.Equals (other) && other.Team == Team;
    }

    public override int GetHashCode()
    {
        unchecked {
            int result = this.Col;
            result = (result * 397) ^ this.Row;
            result = (result * 397) ^ this.Team;
            return result;
        }
    }
}

public class Ant : TeamLocation, IEquatable<Ant> {
    public Ant (int row, int col, int team) : base (row, col, team) {
    }

    public bool Equals (Ant other) {
        return base.Equals (other);
    }
}

2 个答案:

答案 0 :(得分:1)

检查相等性时,需要重写GetHashCode()方法。

public class Ant : IEquatable<Ant>
{
    private string _someField;

    public Ant(string someField)
    {
        this._someField = someField;
    }

    #region Equality members

    public bool Equals(Ant other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }
        return string.Equals(_someField, other._someField);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        if (ReferenceEquals(this, obj))
        {
            return true;
        }
        if (obj.GetType() != this.GetType())
        {
            return false;
        }
        return Equals((Ant) obj);
    }

    public override int GetHashCode()
    {
        return (_someField != null ? _someField.GetHashCode() : 0);
    }

    #endregion
}

您可以选择创建一个IEqualityComparer类来为您进行比较。

 private sealed class SomeFieldEqualityComparer : IEqualityComparer<Ant>
    {
        public bool Equals(Ant x, Ant y)
        {
            if (ReferenceEquals(x, y))
            {
                return true;
            }
            if (ReferenceEquals(x, null))
            {
                return false;
            }
            if (ReferenceEquals(y, null))
            {
                return false;
            }
            if (x.GetType() != y.GetType())
            {
                return false;
            }
            return string.Equals(x._someField, y._someField);
        }

        public int GetHashCode(Ant obj)
        {
            return (obj._someField != null ? obj._someField.GetHashCode() : 0);
        }
    }

答案 1 :(得分:1)

您需要正确实现GetHash和Equals,以使类在搜索/字典中的行为与“比较值”相比,而不是“比较参考”。

另一个(可能更好的选择)是在创建字典时提供IEqualityComparer

示例可以在文章中找到,这里是压缩版本:

Dictionary<Box, String> boxes = 
   new Dictionary<Box, string>(new BoxEqualityComparer());

class BoxEqualityComparer : IEqualityComparer<Box>
{
  public bool Equals(Box b1, Box b2)
  {
    return b1.Height == b2.Height;
  }

  public int GetHashCode(Box bx)
  {
    return bx.Height.GetHashCode();
  }
}