[英]Dictionary using is custom key but key is always unequal
I am using RTBTextPointer as custom key in dictionary... 我正在使用RTBTextPointer作为字典中的自定义键...
Init.SpintaxEditorPropertyMain.SpintaxListDict = new Dictionary<RTBTextPointer, SpintaxEditorProperties.SpintaxMappedValue>(new RTBTextPointerComparer());
I worte this RTBTextPointer, and RTBTextPointerComparer classes in class library and using this in different wpf projects, 我将这个RTBTextPointer和RTBTextPointerComparer类放在类库中,并在不同的wpf项目中使用它,
if (Init.SpintaxEditorPropertyMain.SpintaxListDict.ContainsKey(_index) == false)
{
Init.SpintaxEditorPropertyMain.SpintaxListDict.Add(_index,_SpintaxMappedVal);
}
everytime containsKey returns false, even it contains, so duplication entry occurs in dictionary.. is anything wrong in my "GetHashCode()" 每次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<RTBTextPointer>
{
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;
}
}
Please help me Thanks in advance 请帮我谢谢
Your problem probably stems from the following declarations in RTBTextPointer
: 您的问题可能源于RTBTextPointer
的以下声明:
static int _row;
static int _column;
These don't do what I think you're intending. 这些不符合我的预期。 They should be 他们应该是
private int _row;
private int _column;
As it is right now, these variables reference static
members of RTBTextPointer
. 现在,这些变量引用了RTBTextPointer
static
成员。 This means that any access of them will access or mutate the static
members of it. 这意味着对它们的任何访问都会访问或更改其static
成员。 static
members are accessible to every instance of a type. static
成员可用于类型的每个实例。 If you make them private
, they will apply per instance, which I believe is your intent. 如果将它们private
,则它们将适用于每个实例,我相信这是您的意图。
Once that is corrected, I would reconsider the design of your class, at least if you intent to use it as a key in a Dictionary
. 一旦更正了这一点,至少如果您打算将其用作Dictionary
的键,我将重新考虑您的类的设计。 RTBTextPointer
should be immutable, or atleast the fields and properties that GetHashCode()
depends on. RTBTextPointer
应该是不可变的,或者至少是GetHashCode()
依赖的字段和属性。 Here's why: 原因如下:
When you add a object as a key to a dictionary, it's associated value is placed in a hash bucket , which is simply some data structure associated with a hash code. 当您将对象添加为字典的键时,它的关联值将放在哈希桶中,哈希桶只是与哈希码关联的某些数据结构。 Assume we have some arbitrary key RTBTextPointer
with Row = 2
and Column = 2
and a value of "Foo". 假设我们有一些任意键RTBTextPointer
, Row = 2
和Column = 2
并且值为“ Foo”。 It's GetHashCode would be 0 (2 XOR 2). 它的GetHashCode将为0(2 XOR 2)。
Hash Key Value
0 RTBTextPointer(2,2) Foo
Right now, a call to Dictionary.ContainsKey()
would return true looking for RTBTextPointer(2,2)
. 现在,对Dictionary.ContainsKey()
的调用将在寻找RTBTextPointer(2,2)
返回true。 Now consider if this RTBTextPointer
changed to have a Row = 4
. 现在考虑是否将此RTBTextPointer
更改为Row = 4
。 It's hash code would now be 6 (4 XOR 2). 它的哈希码现在为6(4 XOR 2)。 The call to Dictionary.ContainsKey()
would now be false, and the value Foo
would be inaccessible because the key has a hash code that depends upon mutable state. 现在,对Dictionary.ContainsKey()
的调用将为false,并且值Foo
将不可访问,因为该键具有取决于可变状态的哈希码。
As a final note, I would consider overriding the Equals()
and GetHashCode()
methods of object
. 最后一点,我将考虑重写object
的Equals()
和GetHashCode()
方法。
I don't think you need to create a separate comparer. 我认为您不需要创建单独的比较器。 Just overriding Equals
and GetHashCode
should suffice. 仅覆盖Equals
和GetHashCode
就足够了。
Also, if you have very simple properties like that, you could switch to auto properties 另外,如果您具有类似这样的简单属性,则可以切换到自动属性
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;
}
}
}
See unchecked for more information about that. 有关更多信息,请参见未选中 。
If you have more than two properties, and if those properties could be null, the GetHashCode
might look like this: 如果您有两个以上的属性,并且这些属性可以为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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.