具有相同字段值的类实例的相同字典键

时间:2014-01-27 12:42:45

标签: c# dictionary

  1. 我有这个班级

    class Border
    {
       int top;
       int bottom;
       int left;
       int right;
    }
    
  2. 我有Dictionary Border作为密钥。

  3. 如果这两个值相等,我想为这个类使用相同的键。我该怎么办?

2 个答案:

答案 0 :(得分:4)

因此,如果这些需要作为字典中的键,那么your class needs to be immutable。然后是添加相等性和哈希码实现(thankyou resharper)的情况。

public class Border
{
    private readonly int bottom;
    private readonly int left;
    private readonly int right;
    private readonly int top;

    public Border(int top, int left, int bottom, int right)
    {
        this.top = top;
        this.left = left;
        this.bottom = bottom;
        this.right = right;
    }

    protected bool Equals(Border other)
    {
        return bottom == other.bottom && left == other.left && right == other.right && top == other.top;
    }

    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((Border) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = bottom;
            hashCode = (hashCode*397) ^ left;
            hashCode = (hashCode*397) ^ right;
            hashCode = (hashCode*397) ^ top;
            return hashCode;
        }
    }

    public static bool operator ==(Border left, Border right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Border left, Border right)
    {
        return !Equals(left, right);
    }

    public int Top
    {
        get { return top; }
    }

    public int Bottom
    {
        get { return bottom; }
    }

    public int Left
    {
        get { return left; }
    }

    public int Right
    {
        get { return right; }
    }
}

答案 1 :(得分:0)

我不确定你的意思是否是两个相反的事情之一。

如果您希望确保border的两个不同实例在其值相同的情况下被视为同一个键,那么您需要重新定义相等。

步骤1.实施IEquatable<Border>,虽然您不需要这样做,但它可以让一些事情更快地运行,而其他更简单的代码。

步骤2.添加代码以实现此要求的Equals方法:

public bool Equals(Border other)
{
  return other != null
    && other.bottom == bottom
    && other.top == top
    && other.left == left
    && other.right == right;
}

编辑:正如JLRishe在对另一个答案的评论中指出的那样,如果这个类没有被密封,那么上面的方法应该在空检查之后检查GetType() == other.GetType(),除非它有非常好的理由不这样做)。

步骤3.为object.Equalsobject.GetHashCode添加覆盖:

public override bool Equals(object other)
{
  return Equals(other as Border);
}
public override int GetHashCode()
{
   //This is a simple method without very good distribution, that will serve for many cases, but can be improved upon.
   return (bottom << 24 | bottom >> 8)
     ^ (top << 16 | top >> 16)
     ^ (left << 8 | left >> 8)
     ^ right;
}

现在,在字典中使用时,类的默认行为是将具有相同底部,顶部,左侧和右侧的Border个对象视为同一事物。

或者,也许你的意思是你已经有了这个,并且你希望有两个相同的对象由于某种原因被视为不同(就好像它们没有为它们定义的特定的等效感)。你不能在没有反射发射的纯C#中做到这一点,所以我写了http://www.nuget.org/packages/AisA/几次它是有用的。