本文介绍了WinForms:重写基类中的GetHashCode时,绑定功能被破坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将代码简化为下面的简短示例,以重现该错误。我正在尝试将派生类的值绑定到控件。派生类和绑定逻辑为:

I've simplified my code to the following short example that reproduce the error. I'm trying to bind a value of a derived class to a control. The derived class and the binding logic are:

bindingSource = new BindingSource();
numericUpDown1.DataBindings.Add("Value", bindingSource, nameof(SinglePoint.Val), false, DataSourceUpdateMode.OnPropertyChanged);
bindingSource.DataSource = new[] { new SinglePoint(100) };
[...]
public class SinglePoint : PointList
{
    public SinglePoint(int val) { points.Add(val); }
    public int Val
    {
        get { return points[0]; }
        set
        {
            if (value > 300) value = 300; //(*)
            points[0] = value;
        }
    }
}

因此,在设置时例如,在 NumericUpDown 上的值为500,离开它后,由于行(*),我们应该看到300。如果基类未实现 GetHashCode

As a result, when setting for instance a value of 500 on the NumericUpDown, after leaving it we should see 300 because of line (*). This works if the base class does not implement GetHashCode:

public class PointList
{
    protected List<int> points = new List<int>();
    public PointList() { }
    // UNCOMMENT this and the binding will stop working properly
    //public override int GetHashCode()
    //{
    //    unchecked
    //    {
    //        int hashCode = 17;
    //        foreach (var item in points)
    //            hashCode += 13 * item.GetHashCode();

    //        return hashCode;
    //    }
    //}
}

但是, 如果您尝试取消注释 GetHashCode 实现,则绑定将中断。这意味着在设置500并保留 NumericUpDown 之后,控件仍将显示500,但实际上基础值将为300。为什么会这样,我怎么解决呢?不会拒绝我的自定义实现 GetHashCode

However, if you try to uncomment the GetHashCode implementation, the binding will break. Meaning that after setting 500 and leaving the NumericUpDown, the control will still show 500, but in reality the underlying value will be 300. Why is this happening and how could I solve it without turning down my custom implementation of GetHashCode?

EDIT

正如您中的某些人所指出的,GetHashCode不应更改,因为绑定机制使用了它。这回答了我问题的第一部分。但是,如何使我的PointList类满足其他,如果两个条件相等,则 (...)== true),那么它们必须为GetHashCode()返回相同的值。如果我有两个 PointList 对象,它们具有相同的点列表(序列),我希望它们被发现是相等的(由于代码中的其他逻辑),这意味着相同的哈希码。

As pointed out by some of you, GetHashCode should not change because it is used by the binding mechanism. This reply to the first part of my question. However, how can I make my PointList class satisfying the other rule by which "if two things are equal (Equals(...) == true) then they must return the same value for GetHashCode()". If I have two PointList objects with the same list (sequence) of points I would like them to be found equal (because of other logics in my code), which should imply having the same hash code. How would you do?

推荐答案

经验法则:

请参阅Eric Lippert的文章。

See Eric Lippert's article here.

GetHashCode 您应该仅使用只读或不可变字段;否则,该对象不能在字典哈希表和其他基于哈希的集合中使用。

In the GetHashCode you should use only readonly or immutable fields; otherwise, the object cannot be used in a Dictionary, Hashtable and other hash-based collections.

这篇关于WinForms:重写基类中的GetHashCode时,绑定功能被破坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 15:18