指定された EqualityComparer で作成された HashSet が、Remove 操作でその比較子を使用することを期待しています。特に、Contains 操作が 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 をもう一度見て、何が問題なのかを調べると、答えは実際には上記の投稿されたコードにあります。初めての方にもわかりやすいポイント。
コードを見てくださった皆様、ありがとうございました!