1

我有两个类似这样的对象:

class Container {
    public HashSet<Item> Items { get; }
}

class Item {
    public Container Parent { get; set; }
    public string Value1 { get; set; }
    public int Value2 { get; set; }
}

每个Item实例都必须属于一个Container实例,并且两者之间存在一对多的关系,并且两端始终保持同步。

我现在面临实现一个方法来比较两个实例Item以查看它们Value1Value2值是否匹配。该方法不会考虑该Parent值,因为我比较的每对实例在该值上肯定不同,因此这样做会使我正在实现的方法无用,因为它会具有与false该方法相同的结果 () object.ReferenceEquals

我的问题如下。我应该将此方法实现为对象的public override bool Equals( object obj )方法(连同GetHashCode)吗?还是它忽略了它的Parent属性这一事实阻止了我这样做?为什么或者为什么不?我的另一个想法是只实现它,public bool EqualsIgnoreParent( Item other )它不会覆盖任何东西;然后我可以从自定义比较器中调用它。

4

5 回答 5

1

感谢mikez 的评论和 Eric Lippert 的博客文章,我发现我不应该覆盖Item'sEqualsGetHashCode方法,因为Item's 实例是可变的并添加到HashSet.

按照这里的建议,我决定将相等的两个概念分开。

  1. 身份。我没有覆盖' ItemsEqualsGetHashCode方法。我将这些方法保留在object. 这就是HashSet意志所使用的。
  2. 等价。我创建了一个名为的公共单例类ValueComparer,它嵌套在Item和 implementsIEqualityComparer<Item>中。这就是我在我的问题中描述的比较逻辑的地方。
于 2013-08-07T00:09:41.610 回答
0

我猜你想实现 IEquatable。所以我建议你用 Euqals(Item other) 重载 Euqals(object other),同时通过调用 Equals(Item other) 覆盖 Equals(object other)。

当然,让 GetHashCode 始终返回 -1 以强制通过 Equals 进行相等比较。这里解释了为什么需要覆盖 GetHashCode 方法 -为什么在覆盖 Equals 方法时覆盖 GetHashCode 很重要?

于 2013-08-06T05:26:18.433 回答
0

是的,您可以使用 Equals 和 GetHashCode 来实现这一点,只要 Value1 和 Value2 不变,或者您的哈希值独立于任何 change。(否则使用您的 HashCode 的集合将不起作用)

此外,您可以将 Item 类减少为基本成员

class Item {
    public string Value1 { get; set; }
    public int Value2 { get; set; }
}

并在附加字典中维护关系:(如果您正确实现 GetHashCode,这将是有效的)

Dictionary<Item, Container> ContainersOfItems;
于 2013-08-06T07:33:26.367 回答
0

我建议拆分 Item 可能更有意义,因此它看起来像:

class Container<TContent> {
    public HashSet<Item<TContent>> Items { get; }
}

class Item<TContent> {
    public Container Parent;
    public TContent Content;
}

如果你这样做,那么你可以定义一个类型来保存你的内容,它有一个Equals适合该类型的方法,并使用基于每个's字段的相等性来初始化你HashSet的内容。IEqualityComparer<Item<TConcent>>Item<TContent>Content

于 2013-08-06T22:52:53.843 回答
-1

不要这样做,除非您 100% 确定父成员不会产生任何影响。可能有很多你没有想到的用例,(如果你需要将 2 个容器中的项目放在一个字典中怎么办?)所以我建议坚持设计。如果根据定义,平等仅由其他成员决定,那就去吧。否则,不会。
您以后总是可以编写特定于案例的相等逻辑。请记住Dictionary,,ListHashSet其他集合允许您定义自定义IEqualityComparer
还有另一种选择,但要非常小心。覆盖这两种方法,但GetHashCode比 更宽容Equals,这意味着,使不相等的对象具有相同的哈希码,而不是相反。GetHashCode忽略父成员,但不Equals. 它不会伤害任何东西,然后如果您想忽略字典中的 Parent 成员,请编写一个IEqualityComparer以相同方式比较它们的GetHashCode.

于 2013-08-06T09:43:33.437 回答