我有一个负责创建(和保存)新患者的表格。在这个表单上,我使用ErrorProvider在无效字段上显示错误图标(在这种情况下只是" LastName")。所以,像往常一样=> errorProvider.DataSource = patient;
当我的模型使用默认的GetHashCode()时,一切正常。但是当我尝试使用自定义哈希代码覆盖此方法时(我想将此模型与ISet集合一起使用),控件无法正常工作。现在,我知道自定义哈希码应仅用于不可变对象。但问题是,如果ErrorProvider行为在GetHashCode上继续正常工作,我如何填充这些对象的字段?是否有必要实现一个在默认哈希码(在对象初始化期间)和自定义哈希值之间切换的脏机制?
代码示例:
public class Patient : IDataErrorInfo, INotifyPropertyChanged
{
public string lastName;
public virtual string LastName
{
get { return lastName; }
set
{
if (lastName == value) return;
lastName = value;
NotifyPropertyChanged("LastName");
}
}
#region IDataErrorInfo Members
string IDataErrorInfo.Error { get { return null; } }
string IDataErrorInfo.this[string propertyName]
{
get { return this.GetValidationError(propertyName); }
}
#endregion // IDataErrorInfo Members
protected string GetValidationError(string propertyName)
{
if (ValidatedProperties.IndexOf(propertyName) < 0)
return null;
string error = null;
switch (propertyName)
{
case "LastName":
if (LastName == null)
error = "null";
break;
default:
break;
}
return error;
}
public virtual event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public override int GetHashCode()
{
unchecked
{
int result = 17;
result = 23 * result + ((LastName != null) ? LastName.GetHashCode() : 0);
return result;
}
}
}
答案 0 :(得分:0)
GetHashCode
函数中使用的每个字段都必须是不可变的。我不建议实现两个版本的GetHashCode
,因为它应该是持久且可重复的。我知道如何解决这个问题的一种可能方法。如果您知道某个对象将被更改,则可以在编辑操作之前将其从集中删除,并在完成所有修改后再次添加到集中。在这种情况下,您可以跳过覆盖GetHashCode
并使用SortedSet与指定的实现IComparer接口的比较器。
更新
通常情况下,如果您不需要排序集,我建议您使用HashSet
。 SortedSet
使用二叉搜索树,似乎它没有使用GetHashCode
函数。 SortedSet
比HashSet
慢一点。 SortedSet
性能约为 O(log n),因为它必须在有序集中找到插入元素的空间。 HashSet只接受 O(1)。
IComparer
有助于找出两个对象是否相等(无需调用Equals
)或告诉它们哪个小于或大于其他对象。我写了一些用于测试SortedSet功能的代码。
public class Foo
{
public Foo(string something)
{
Something = something;
}
public string Something { set; get; }
}
public class BySomething : IComparer<Foo>
{
private readonly CaseInsensitiveComparer _comparer = new CaseInsensitiveComparer();
public int Compare(Foo x, Foo y)
{
return _comparer.Compare(x.Something, y.Something);
}
}
[TestMethod]
public void SortedSetTest()
{
var first = new Foo("Doe");
var second = new Foo("Floyd");
var third = new Foo("Floyd");
var set = new SortedSet<Foo>(new BySomething());
set.Add(first);
set.Add(second);
set.Add(third);
Assert.AreEqual(set.Count, 2);
}