2010-09-01 166 views
5

我期待已經使用指定的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的創建&的類,然後再看看比較器來找出它的錯誤。輕鬆點第一個人發現它。

感謝所有看過代碼的人!

+2

Post'DurationExcludedEqualityComparer'。 – 2010-09-01 21:58:59

+0

我猜想你的'DurationExcludedEqualityComparer'中的平等實現是可疑的。 – adrianbanks 2010-09-01 22:00:55

+0

你的'Allocation'類(以及任何'Resource'和'Activity'引用)是什麼樣的? – adrianbanks 2010-09-01 22:10:08

回答

1

那麼,你的代碼「工作」似乎看StartTimeResource,而忽略Activity,而你的IEqualityComparer<Allocation>執行看起來全部三。你的問題可能與此有關嗎?

另外:你的StartTime,ResourceActivity屬性不變?否則,由於它們會影響您的GetHashCode結果,我認爲您冒着破壞HashSet<Allocation>的風險。

+0

賓果在第一行。我不太確定它是否是某種遞歸,但在這種情況下,它是一個擁有HashSet的Activity。在添加分配方法(ClockIn)中放置一個警戒來檢查屬於'this'活動的分配,並且在任何事件中將比較方法中的Activity都取出來更合理,並通過返回一致的哈希來解決問題。乾杯! – Berryl 2010-09-02 02:39:34