HashSet.Remove不能与EqualityComparer一起工作
我期待已经使用指定的EqualityComparer创建的HashSet在Remove操作上使用该比较器。特别是因为Contains操作返回true!HashSet.Remove不能与EqualityComparer一起工作
这里是我使用的代码:
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);
}
任何人都可以提出为什么删除会失败,当包含成功?
干杯,
Berryl
===编辑===比较程序
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的创建&的类,然后再看看比较器来找出它的错误。轻松点第一个人发现它。
感谢所有看过代码的人!
那么,你的代码“工作”似乎看StartTime
和Resource
,而忽略Activity
,而你的IEqualityComparer<Allocation>
执行看起来全部三。你的问题可能与此有关吗?
另外:你的StartTime
,Resource
和Activity
属性不变?否则,由于它们会影响您的GetHashCode
结果,我认为您冒着破坏HashSet<Allocation>
的风险。
宾果在第一行。我不太确定它是否是某种递归,但在这种情况下,它是一个拥有HashSet的Activity。在添加分配方法(ClockIn)中放置一个警戒来检查属于'this'活动的分配,并且在任何事件中将比较方法中的Activity都取出来更合理,并通过返回一致的哈希来解决问题。干杯! – Berryl 2010-09-02 02:39:34
Post'DurationExcludedEqualityComparer'。 – 2010-09-01 21:58:59
我猜想你的'DurationExcludedEqualityComparer'中的平等实现是可疑的。 – adrianbanks 2010-09-01 22:00:55
你的'Allocation'类(以及任何'Resource'和'Activity'引用)是什么样的? – adrianbanks 2010-09-01 22:10:08