如何确定两个HashSet是否相等(按值比较,而不是按引用比较)?

86

我正在尝试确定在.NET 3.5(C#)中两个HashSet对象是否相等,即包含相同的值。这似乎是一个显而易见的需求,但提供的函数都无法给出此信息。

我想到的方法是检查这两个集合的计数是否相等,并且其中一个集合是另一个集合的子集(非真子集)。如果发生这种情况,我认为它们就是相等的集合。以下是示例代码:

HashSet<int> set1 = new HashSet<int>();
set1.Add(1);
set1.Add(2);
set1.Add(3);

HashSet<int> set2 = new HashSet<int>();
set2.Add(1);
set2.Add(2);
set2.Add(3);

if(set1.Count == set2.Count && set1.IsSubsetOf(set2))
{
    // do something
}

这样始终有效吗?有更好的方法吗?为什么HashSet没有一个public bool IsEqualSetWith()函数?


虽然 SetEquals() 方法可以达到目的,但从良好的面向对象编程角度来看,这显然不是最理想的解决方案。理想情况下,我希望能够使用 ICollection<T> 或者 IEnumerable<T> 这样的接口进行操作。在为其他开发人员提供平台时,这些并不是完美主义象牙塔,而是非常现实的 API 设计考虑因素。总之,如果我的 API 接受 ICollection<T> 作为参数,则希望能够调用 .Equals() 方法将该参数与某个已知值进行比较。如果调用方给了我一个列表,并且我在 API 方法中将其与集合进行比较(续) - Mark Arrowsmith
我希望我的set对象能够识别出它是一个列表并返回false。相反,如果调用者使用一个set并且它恰好具有相同的元素,我希望我的set对象在不需要我强制转换和使用特殊方法的情况下内部调用SetEquals()。换句话说,像学校里教的那样使用多态和封装。令我震惊的是,C#库如此之久都没有解决这个问题,而且没有人抱怨。 - Mark Arrowsmith
3
它被称为IEqualityComparer :) - Billy ONeal
4
SetEquals 没有问题。 - Jared Kells
1
请注意,添加的顺序与哈希集相等无关。 - Ehsan88
对于任何想要访问 SetEquals 的接口,可以使用 System.Collections.Generic 中的 ISet<T> - Steve Lillis
2个回答

156

请查看方法 SetEquals

my_hashset.SetEquals(other);

谢谢Michael,我不知道我是怎么在MSDN的方法列表里完全错过了那个... - Craig W
56
每个人都会有这种经历。我简直不敢相信我在一个 .NET 问题上击败了 Jon Skeet 和 Marc Gravell。我猜他们也得睡觉吧。 - Michael Burr
1
容易被忽略。如果不仔细注意,使用前缀“Set”的方法看起来像是一个改变器。 - Merlyn Morgan-Graham
@MerlynMorgan-Graham:我从来没有在集合论的背景下这样想过,但无论如何,这是一个有趣的发现。 - Mustafa Özçetin

5
IEqualityComparer<HashSet<int>> comp = HashSet<int>.CreateSetComparer();
Console.WriteLine("CreateSetComparer set1 == set2 : {0}", comp.Equals(set1, set2));
// or
bool areEqual = HashSet<int>.CreateSetComparer().Equals(set1, set2);

当你需要创建一个以HashSet作为键的字典时,这将非常有用。 - mancze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接