问题描述
我已将代码简化为下面的简短示例,以重现该错误。我正在尝试将派生类的值绑定到控件。派生类和绑定逻辑为:
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时,绑定功能被破坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!