目前我遇到了问题,当我覆盖GetHashCode
和Equals
时,我的绑定会被破坏。
这是我的模特:
class A
{
private string name;
public string Name
{
get { return name; }
set { name = value; /*Some notification stuff*/ }
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
else if (obj is A)
{
return (obj as A).Name == this.name;
}
else
{
return false;
}
}
public override int GetHashCode()
{
if (name != null)
{
return name.GetHashCode();
}
else
{
return 0;
}
}
}
class B
{
private ObservableCollection<A> items;
private A selectedItem;
public ObservableCollection<A> Items
{
get { return items; }
set { items = value; /*Some notification stuff*/ }
}
public A SelectedItem
{
get { return selectedItem; }
set { selectedItem = value; /*Some notification stuff*/ }
}
}
xaml如下:
<Label Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Content="A:" />
<TextBox Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="24"
Text="{Binding SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, diagnostics:PresentationTraceSources.TraceLevel=High}" />
<Label Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="List" />
<ListBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
ItemsSource="{Binding Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, diagnostics:PresentationTraceSources.TraceLevel=High,
ValidatesOnDataErrors=True}" DisplayMemberPath="Name" />
问题是,如果我覆盖GetHashCode
和Equals
,绑定仅在第一次选择项目并更改名称时才起作用。之后它似乎破碎了。我已经添加了一些绑定调试,但这不会返回任何错误或分离/停用。
如果我删除了覆盖,每个想法都可以。
我在这里做错了吗?
答案 0 :(得分:2)
覆盖Equals
在你的情况下看起来没问题,它不会破坏任何东西。
但是以这种方式覆盖GetHashCode
(即在计算哈希码时使用带有公共setter的属性)将破坏使用哈希码从集合中检索类A
项(例如,来自{{ 1}})如果你在添加到集合后改变这个属性值。
您也可以从Eric Lippert的博客中找到有关GetHashCode指南和规则的有趣this article。
答案 1 :(得分:1)
您的解决方案是可以接受的。
考虑将A
设为sealed class
或检查this.GetType() == obj.GetType()
(当然obj
不为空的情况)。如果this
的派生程度高于obj
,或obj
的派生程度高于this
,则应返回false。
覆盖GetHashCode
时,切勿保持Equals
的基类行为。
正如Andy Korneyev在他的回答中所说,请注意一个可变对象Equals
(因此也GetHashCode
)可以在将实例添加到Hashtable
Dictionary<,>
后更改HashSet<>
1}},.procmailrc
等可能很危险。如果对象在哈希表保存对它的引用时发生了变异,那么该哈希表将被搞砸,并且该对象可能无法在该哈希表中的O(1)查找中找到。