1

我正在使用 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);
        }

每次 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;
    }
}

请帮助我提前谢谢

4

2 回答 2

1

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

static int _row;
static int _column;

这些不符合我认为你的意图。他们应该是

private int _row; 
private int _column; 

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

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

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

Hash Key                  Value
0    RTBTextPointer(2,2)  Foo

现在,调用 toDictionary.ContainsKey()将返回 true 寻找RTBTextPointer(2,2)。现在考虑是否将其RTBTextPointer更改为具有Row = 4. 它的哈希码现在是 6(4 XOR 2)。对的调用Dictionary.ContainsKey()现在将是错误的,并且该值Foo将无法访问,因为键具有取决于可变状态的哈希码。

最后一点,我会Equals()考虑GetHashCode()覆盖object.

于 2013-09-04T05:11:29.503 回答
1

我认为您不需要创建单独的比较器。只是压倒一切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;
        }
    }
}

有关这方面的更多信息,请参见未选中。

如果您有两个以上的属性,并且这些属性可能为空,则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;
}
于 2013-09-04T05:12:38.740 回答