具有自定义 GetHashCode 的错误提供程序

本文关键字:程序 错误 自定义 GetHashCode | 更新日期: 2023-09-27 18:33:20

我有一个负责创建(和保存(新患者的表格。在此表单上,我使用错误提供程序在无效字段上显示错误图标(在本例中仅为"姓氏"(。所以,像往常一样 => 错误提供者.数据源 = 患者;

当我的模型使用默认的 GetHashCode(( 时,一切正常。但是当我尝试使用自定义哈希代码重写此方法时(我想将此模型与 ISet 集合一起使用(,控件无法正常工作。现在,我明白自定义哈希代码应该仅用于不可变对象。但关键是,如果错误提供程序行为中继在 GetHashCode 上正常工作,我该如何填写这些对象的字段?是否有必要实现在默认哈希代码(对象初始化期间(和自定义哈希之间切换的 Dirty 机制?

代码示例:

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

具有自定义 GetHashCode 的错误提供程序

函数中使用的每个字段都必须是不可变GetHashCode。我不建议实现两个版本的GetHashCode,因为它应该是持久和可重复的。我知道一种可能的方法可以解决这个问题。如果您知道某个对象将被更改,则可以在编辑操作之前将其从集合中删除,并在完成所有修改后再次添加到集合中。在这种情况下,您可以跳过GetHashCode的覆盖,并将 SortedSet 与实现 IComparer 接口的指定比较器一起使用。

更新

通常,如果您不需要排序集,我建议您使用 HashSet 因此。 SortedSet使用二叉搜索树,似乎它不使用GetHashCode函数。 SortedSetHashSet慢一点。 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);
}