字典使用是自定义键,但键始终不相等
我在字典中使用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; } }
请帮助我提前谢谢
我认为你不需要创建一个单独的比较器。 只需覆盖Equals
和GetHashCode
就足够了。
此外,如果您具有非常简单的属性,则可以切换到自动属性
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 = 2
且Column = 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
将无法访问,因为该键具有依赖于可变状态的哈希码。
最后,我会考虑重写object
的Equals()
和GetHashCode()
方法。