字典使用是自定义键,但键始终不相等
本文关键字:不相等 字典 自定义 | 更新日期: 2023-09-27 18:30:14
我正在使用RTBTextPointer 作为字典中的自定义键...
Init.SpintaxEditorPropertyMain.SpintaxListDict = new Dictionary<RTBTextPointer, SpintaxEditorProperties.SpintaxMappedValue>(new RTBTextPointerComparer());
我在类库中使用这个RTBTextPointer和RTBTextPointerComparer类,并在不同的wpf项目中使用它,
if (Init.SpintaxEditorPropertyMain.SpintaxListDict.ContainsKey(_index) == false)
{
Init.SpintaxEditorPropertyMain.SpintaxListDict.Add(_index,_SpintaxMappedVal);
}
每次包含密钥都返回 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;
}
}
请帮助我提前致谢
我认为您不需要创建一个单独的比较器。只需覆盖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;
就像现在一样,这些变量引用static
RTBTextPointer
的成员。这意味着它们的任何访问都将访问或改变其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()
会返回真正的寻找RTBTextPointer(2,2)
。现在考虑一下这个RTBTextPointer
是否更改为具有Row = 4
。它的哈希代码现在是 6(4 XOR 2)。对Dictionary.ContainsKey()
的调用现在将为 false,并且Foo
的值将无法访问,因为密钥具有依赖于可变状态的哈希代码。
最后,我会考虑覆盖object
的Equals()
和GetHashCode()
方法。