字典使用是自定义键,但键始终不相等

我在字典中使用RTBTextPointer作为自定义键…

Init.SpintaxEditorPropertyMain.SpintaxListDict = new Dictionary(new RTBTextPointerComparer()); 

我在类库中编写RTBTextPointer和RTBTextPointerComparer类,并在不同的wpf项目中使用它,

  if (Init.SpintaxEditorPropertyMain.SpintaxListDict.ContainsKey(_index) == false) { Init.SpintaxEditorPropertyMain.SpintaxListDict.Add(_index,_SpintaxMappedVal); } 

everytime containsKey返回false,即使它包含,所以在字典中出现重复条目​​..我的“GetHashCode()”中有任何错误

  public class RTBTextPointer { static int _row; static int _column; public int Row { get { return _row; } set { _row = value; } } public int Column { get { return _column; } set { _column = value; } } } public class RTBTextPointerComparer : IEqualityComparer { public bool Equals(RTBTextPointer x, RTBTextPointer y) { bool result = int.Equals(x.Column, y.Column) && (int.Equals(x.Row, y.Row)); return result; } public int GetHashCode(RTBTextPointer obj) { var result = 0; int hCode = obj.Column ^ obj.Row; result = hCode.GetHashCode(); return result; } } 

请帮助我提前谢谢

我认为你不需要创建一个单独的比较器。 只需覆盖EqualsGetHashCode就足够了。

此外,如果您具有非常简单的属性,则可以切换到自动属性

 public class RTBTextPointer { public int Row { get; set; } public int Column { get; set; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } var other = obj as RTBTextPointer; if (other == null) { return false; } return other.Row == Row && other.Column == Column; } public override int GetHashCode() { unchecked { // 397 or some other prime number return (Row * 397) ^ Column; } } } 

有关详细信息,请参阅未选中 。

如果您有两个以上的属性,并且这些属性可能为null,则GetHashCode可能如下所示:

 unchecked { var result = 0; result = (result * 397) ^ (Prop1 != null ? Prop1.GetHashCode() : 0); result = (result * 397) ^ (Prop2 != null ? Prop2.GetHashCode() : 0); result = (result * 397) ^ (Prop3 != null ? Prop3.GetHashCode() : 0); result = (result * 397) ^ (Prop4 != null ? Prop4.GetHashCode() : 0); // ... return result; } 

您的问题可能源于RTBTextPointer的以下声明:

 static int _row; static int _column; 

这些没有做我认为你想要的。 他们应该是

 private int _row; private int _column; 

就像现在一样,这些变量引用了RTBTextPointer static成员。 这意味着对它们的任何访问都将访问或改变它的static成员。 static成员可供类型的每个实例访问。 如果你将它们private ,它们将适用于每个实例,我相信这是你的意图。

一旦纠正,我会重新考虑你的类的设计,至少如果你打算将它用作Dictionary的键。 RTBTextPointer应该是不可变的,或者至少是GetHashCode()依赖的字段和属性。 原因如下:

当您将对象作为键添加到字典时,它的关联值被放置在散列桶中,这只是与散列码相关联的一些数据结构。 假设我们有一些任意键RTBTextPointer其中Row = 2Column = 2 ,值为“Foo”。 它的GetHashCode为0(2 XOR 2)。

 Hash Key Value 0 RTBTextPointer(2,2) Foo 

现在,对Dictionary.ContainsKey()的调用将返回true,查找RTBTextPointer(2,2) 。 现在考虑这个RTBTextPointer更改为Row = 4 。 它的哈希码现在是6(4 XOR 2)。 对Dictionary.ContainsKey()的调用现在将为false,并且值Foo将无法访问,因为该键具有依赖于可变状态的哈希码。

最后,我会考虑重写objectEquals()GetHashCode()方法。