根据要在HashSet中使用的类属性定义相等性

时间:2016-06-27 13:30:35

标签: c#

我有以下课程:

public class OrderRule {
  public OrderDirection Direction { get; set; }
  public String Property { get; set; }
}

它的HashSet:

HashSet<OrderRule> rules = // ...

如果属性相等,我需要将OrderRules视为相等。

我该怎么做?

2 个答案:

答案 0 :(得分:4)

由于此等式的规范不是来自OrderRule类,而是来自您的集合,因此请使用接受IEqualityComparer的HashSet的构造函数重载。

public class MyOrderRuleComparer : EqualityComparer<OrderRule>
{
    private IEqualityComparer<string> _c = EqualityComparer<string>.Default;

    public override bool Equals(OrderRule l, OrderRule r)
    {
        return _c.Equals(l.Property, r.Property);
    }

    public override int GetHashCode(OrderRule rule)
    {
        return _c.GetHashCode(rule.Property);
    }
}

...

HashSet<OrderRule> rules = new HashSet(new MyOrderRuleComparer());

请注意,通过使用OrderRule.Property作为键,您意味着在将实例添加到集合后它不能更改。这就是为什么实施IEquatable<OrderRule>可能是最好的方法,具体取决于您的开发团队。

答案 1 :(得分:3)

  

如果我添加两个具有相同属性但方向不同的OrderRules   仍然需要两者被认为是平等的

您可以覆盖EqualsGethashCode和/或实施IEquatable<OrderRule>

public class OrderRule: IEquatable<OrderRule>
{
    public OrderRule(string property)
    {
        this.Property = property;
    }

    public OrderDirection Direction { get; set; }
    public String Property { get; }
    public OrderRule Rule { get; set; }

    public bool Equals(OrderRule other)
    {
        return (other != null && other.Property == this.Property);
    }

    public override int GetHashCode()
    {
        return Property?.GetHashCode() ?? int.MinValue;
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        if(ReferenceEquals(this, obj))
            return true;
        OrderRule other = obj as OrderRule;
        return this.Equals(other);
    }
}

请注意,我已将该属性设置为只读,因为您无法修改GetHashCode中使用的属性或字段。

Why?“指南:GetHashCode返回的整数永远不会改变 理想情况下,可变对象的哈希码应仅从不能变异的字段计算,因此对象的哈希值在其整个生命周期内都是相同的。“

此值为f.e.在字典或HashSet中用于计算哈希码。如果在添加对象后它会发生变化,则无法再找到它。