如何使用HashSet 删除MyCustomClass的重复项?

我有一个HashSet mySet = new HashSet(); 我希望删除包含相同值的所有MyCustomClass。

假设MyCustomClass看起来像这样:

 public class MyCustomClass { Point point; public MyCustomClass(int x, int y) { point.X = x; point.Y = y; } // Other methods... } 

我尝试像MSDN建议的那样实现IEqualityComparer ,并将其传递给HashSet();的构造函数HashSet(); 但我最终失败了。

什么是正确的方法?

编辑:

这是我的Chain类和我的ChainEqualityComparer

 public class Chain { HashSet chain; HashSet marks; public Chain(HashSet marks) { chain = new HashSet(); this.marks = marks; } // Other methods... } public class ChainEqualityComparer : IEqualityComparer { #region IEqualityComparer Members public bool Equals(Chain x, Chain y) { if (x.ChainWithMarks.Count == y.ChainWithMarks.Count) { foreach (Mark mark in x.ChainWithMarks) { if (!y.ChainWithMarks.Contains(mark)) return false; } return true; } return false; } public int GetHashCode(Chain obj) { return obj.GetHashCode() ^ obj.GetType().GetHashCode(); } #endregion } 

这是我的Mark课程:

  public class Mark { int x; int y; public Mark(int x, int y) { this.x = x; this.y = y; } public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } } public class MarkEqualityComparer : IEqualityComparer { #region IEqualityComparer Members public bool Equals(Mark x, Mark y) { return (xX == yX) && (xY == yY); } public int GetHashCode(Mark obj) { return obj.GetHashCode() ^ obj.GetType().GetHashCode(); } #endregion } 

(如果代码太多,我可以将代码粘贴到代码中……)

您可以使用EqualityComparer或仅覆盖Equals和GetHashCode。

您必须确保将您认为是重复的任何内容标识为具有等效的哈希码,并在测试相等时返回true。

我的猜测是你没有返回相同的哈希码。 你可以发布相等比较器的代码吗?

作为测试,您可以:

 var set = new HashSet(); var a = new MyCustomClass(1,2); var b = new MyCustomClass(1,2); set.Add(a); set.Add(b); Assert.IsTrue(a.Equals(b)); Assert.IsTrue(b.Equals(a)); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); Assert.AreEqual(1, set.Count); 

一组类似的测试也适用于相等比较器。

编辑

是的,怀疑它是哈希码function。 您需要根据类型本身的值来计算它。 一个常见的错误。

 public int GetHashCode(Mark obj) { return ((MyCustomClass)obj).point.GetHashCode(); } 

假定point是您类型中唯一的状态字段。

我认为你被绊倒了因为两个具有相同值的Mark实例在你的ChainEqualityComparer类中是不相等的。 看起来似乎没有使用过MarkEqualityComparer

这条线:

 if (!y.ChainWithMarks.Contains(mark)) 

除非您在Mark类上重写EqualsGetHashCode ,否则将始终为false。 (除非你在链x和链y中都有两个相同标记的引用,我认为这不是你想要的)。

如果y.ChainWithMarks是HashSet并且您想要使用MarkEqualityComparer ,请确保使用MarkEqualityComparer实例的正确构造函数创建该HashSet。

由于Mark是值类型,因此您可以考虑使用结构来表示它,因为.Net运行时在比较时使用值相等而不是引用相等。 我认为这实际上是你的想法最正确的实现。