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;
}
}
}
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;
// }
//}
}
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
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?