【问题标题】:How to override Equals and GetHashCode with two different combinations of equality如何用两种不同的相等组合覆盖 Equals 和 GetHashCode
【发布时间】:2014-09-30 18:00:33
【问题描述】:

我正在创建一个包含多个属性的自定义类的集合。下面是课程。

public class OnlineProductHierarchy
{
    public DateTime InsertDate { get; set; }
    public string InsertUserId { get; set; }
    public DateTime AmendDate { get; set; }
    public string AmendUserId { get; set; }
    public string Product { get; set; }
    public string TextField { get; set; }
    public string Value { get; set; }
    public bool IsDefault { get; set; }
}

为了让我的班级的两个对象被认为是相等的,TextFieldValueProduct 必须相同,或者 TextFieldValue 属性必须相同,如果 IsDefault 是真的

所以我有两种不同的方法来衡量平等,如果其中一种是真的,那么对象应该被认为是平等的。我这样做是为了在创建集合时使用 HashSet 来删除重复项。

使用普通列表并通过 LINQ 比较属性不是一种选择,因为我需要良好的性能。

到目前为止,我有此代码检查我的第一个条件之间的相等性,但我不确定如何修改它以包含我的第二个质量条件

 public override bool Equals(object obj)
    {
        OnlineProductHierarchy o = obj as OnlineProductHierarchy;

        return o != null && o.Product.ToUpper()
      == this.Product.ToUpper() &&  o.Value.ToUpper() == this.Value.ToUpper()
      && o.TextField.ToUpper() == this.TextField.ToUpper();
    }

    public override int GetHashCode()
    {
        return this.Product.ToUpper().GetHashCode() ^ 
        this.TextField.ToUpper().GetHashCode()
      ^ this.Value.ToUpper().GetHashCode();
    }

当添加到 TextFieldValueProduct 规则的 hastset 时,此代码现在可以正确识别重复项,但我如何添加到此以包含我的第二条规则?

编辑

在 cmets 的帮助和回答下,似乎无法在单个 Equals + GetHashCode 方法中做我想做的事。

因此,@Lee 建议的我的替代解决方案是创建两个具有不同 IEqualityComparer 实现的 HastSet,如果在添加时其中任何一个失败,我可以识别重复记录。

【问题讨论】:

  • 请记住,Equals 和 GetHashCode 应该遵循传递相等,即。如果a == bb == c,那么a == c。您不能保证这一点,因此您将遇到大问题。我会建议找到一种不同的方式来做到这一点。
  • 如果没有“自然”平等措施,则创建 IEqualityComparer<OnlineProductHierarchy> 的实现并将它们传递给任何集合。
  • @Lee 有没有办法将两个不同的 IEqualityComparer 传递给同一个集合?在 HashSet 的构造函数中,我只看到一个选项。那么我是否正确地假设我必须创建两个不同的集合并比较结果?

标签: c# hashcode equality


【解决方案1】:

这可能会起作用,但正如@Lasse 建议的那样,您需要小心:

public override bool Equals(object obj)
{
    OnlineProductHierarchy o = obj as OnlineProductHierarchy;

    if(o == null) return false;

    return (String.Compare(o.Product, this.Product, true) &&
           String.Compare(o.Value, this.Value, true) &&
           String.Compare(o.TextField, this.TextField, true))
           ||
           (o.IsDefault == this.Isdefault &&
           String.Compare(o.Value, this.Value, true) &&
           String.Compare(o.TextField, this.TextField, true));
}

public override int GetHashCode()
{
    //Not possible using your logic
}

【讨论】:

  • 我认为这不会起作用,因为 IsDefault 属性仅与第二条规则相关。因此,如果 Product、TextField 和 Value 相同,尽管 IsDefault 值相同,则应将对象视为相等。因此,我认为当 IsDefault 为真以及其他三列时,这不会将对象重新确定为相等。我的帖子可能没有说清楚
  • 那么就不能写GetHashCode函数了。
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
相关资源
最近更新 更多