5

我期望使用指定的 EqualityComparer 创建的 HashSet 在 Remove 操作中使用该比较器。特别是因为包含操作返回 true!

这是我正在使用的代码:

public virtual IEnumerable<Allocation> Allocations { get { return _allocations; } }
private ICollection<Allocation> _allocations; 

public Activity(IActivitySubject subject) {    // constructor
    ....
    _allocations = new HashSet<Allocation>(new DurationExcludedEqualityComparer());
}

public virtual void ClockIn(Allocation a)
{
    ...
    if (_allocations.Contains(a)) 
        _allocations.Remove(a);
    _allocations.Add(a);
}

下面是一些快速而肮脏的 LINQ,它让我得到了我想要的逻辑,但我猜测基于 EqualityComparer 的 HashSet 删除会明显更快。

public virtual void ClockIn(Allocation a)
{
    ...
    var found = _allocations.Where(x => x.StartTime.Equals(a.StartTime) && x.Resource.Equals(a.Resource)).FirstOrDefault();
    if (found != null)
    {
            if (!Equals(found.Duration, a.Duration))
            {
                found.UpdateDurationTo(a.Duration);
            }
    }
    else
    {
            _allocations.Add(a);
    }

任何人都可以建议为什么包含成功时删除会失败吗?

干杯,
贝里尔

=== 编辑 === 比较器

public class DurationExcludedEqualityComparer : EqualityComparer<Allocation>
{
    public override bool Equals(Allocation lhs, Allocation rhs)
    {
        if (ReferenceEquals(null, rhs)) return false;
        if (ReferenceEquals(lhs, null)) return false;
        if (ReferenceEquals(lhs, rhs)) return true;

        return 
            lhs.StartTime.Equals(rhs.StartTime) &&
            lhs.Resource.Equals(rhs.Resource) && 
            lhs.Activity.Equals(rhs.Activity);
    }

    public override int GetHashCode(Allocation obj) {
        if (ReferenceEquals(obj, null)) return 0;
        unchecked
        {
            var result = 17;
            result = (result * 397) ^ obj.StartTime.GetHashCode();
            result = (result * 397) ^ (obj.Resource != null ? obj.Resource.GetHashCode() : 0);
            result = (result * 397) ^ (obj.Activity != null ? obj.Activity.GetHashCode() : 0);
            return result;
        }
    }
}

=== 更新 - 已修复 ===

好吧,好消息是 HashSet 没有损坏并且完全按照它应该的方式工作。对我来说,坏消息是当我在检查树上的叶子时看不到森林时,我是多么愚蠢!

答案实际上在上面发布的代码中,如果您查看创建和拥有 HashSet 的类,然后再查看 Comparer 以找出问题所在。第一个发现它的人的简单点。

感谢所有查看代码的人!

4

1 回答 1

1

好吧,您的“有效”代码似乎在忽略StartTime,而您的实现则着眼于所有三个。您的问题可能与此有关吗?ResourceActivityIEqualityComparer<Allocation>

另外:您的StartTime,ResourceActivity属性是否不变?否则,由于它们会影响您的GetHashCode结果,我认为您冒着破坏HashSet<Allocation>.

于 2010-09-02T00:57:00.817 回答