I am expecting a HashSet that has been created with a specified EqualityComparer to use that comparer on a Remove operation. Especially since the Contains operations returns true!
Here is the code I am using:
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);
}
Below is some quick and dirty LINQ that gets me the logic I want, but I am guessing the HashSet remove based on the EqualityComparer would be significantly faster.
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);
}
Can anyone suggest why the Remove would fail when the Contains succeeds?
Cheers,
Berryl
=== EDIT === the comparer
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;
}
}
}
=== UPDATE - FIXED ===
Well, the good news is that HashSet is not broken and works exactly as it should. The bad news, for me, is how incredibly stupid I can be when not being able to see the forest while examining the leaves on the trees!
The answer is actually in the posted code above, if you look at the class creating & owning the HashSet, and then taking another look at the Comparer to find out what is wrong with it. Easy points for the first person to spot it.
Thanks to all who looked at the code!
Well, your code that "works" appears to look at StartTime
and Resource
while ignoring Activity
, whereas your IEqualityComparer<Allocation>
implementation looks at all three. Could your problem be related to that?
Also: are your StartTime
, Resource
, and Activity
properties unchanging? Otherwise, since they affect your GetHashCode
result, I think you run the risk of breaking your HashSet<Allocation>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With