2017-01-05 29 views
3

我想實現的是對一個日期比較容忍的IEqualityComparer。我也看過this question。問題是我無法使用解決方法,因爲我在LINQ .GroupJoin()中使用IEqualityComparer。我已經嘗試了一些允許寬容的實現。我可以讓Equals()工作,因爲我有兩個對象,但我不知道如何實現GetHashCode()使用的IEqualityComparer的GetHashCode的公差

我最好的嘗試看起來是這樣的:

public class ThingWithDateComparer : IEqualityComparer<IThingWithDate> 
{ 
    private readonly int _daysToAdd; 

    public ThingWithDateComparer(int daysToAdd) 
    { 
     _daysToAdd = daysToAdd; 
    } 

    public int GetHashCode(IThingWithDate obj) 
    { 
     unchecked 
     { 
      var hash = 17; 
      hash = hash * 23 + obj.BirthDate.AddDays(_daysToAdd).GetHashCode(); 
      return hash; 
     } 
    } 

    public bool Equals(IThingWithDate x, IThingWithDate y) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public interface IThingWithDate 
{ 
    DateTime BirthDate { get; set; } 
} 

隨着.GroupJoin()建設HashTableGetHashCode()它適用的日子同時添加到/所有對象。這不起作用。

+0

是daysTo添加寬容,因爲在1月5日等於1月6日容忍1天?這種相等的定義不是傳遞性的,所以我懷疑可以在每個對象返回相同哈希碼的簡單解決方案之外正確使用IEqualityComparer來實現。 –

+0

忘記它。將'GroupJoin'替換爲'SelectMany'和簡單的'Where'(不是很高效,但應該可以工作)。 –

+0

@mikez是的,那是寬容。命名很糟糕。如果我無法完成這項工作,我將只實現一個定製版本的'GroupJoin()'。 –

回答

2

的問題是不可能的,在概念上。您試圖以一種不具有您嘗試執行的操作所需的平等形式的方式比較對象。例如,GroupJoin取決於如下假設:如果A等於B,B等於C,那麼A等於C,但在您的情況下,情況並非如此。 A和B可能「足夠接近」在一起,因爲你想分組它們,但A和C可能不一樣。

你將需要不落實IEqualityComparer可言,因爲你不能滿足其需要的合同。如果你想創建一個集合中的項目到另一個集合中「足夠接近」的所有項目的映射,那麼你將需要自己編寫該算法(這麼做很有效率很可能很難,但這樣做效率不高,不應該那麼困難),而不是使用GroupJoin,因爲它無法執行該操作。

+0

這似乎是正確的答案。答案是沒有答案,這是令人失望的。 –

1

我看不到任何方式產生了給定的標準邏輯哈希碼。
哈希碼用於確定2個日期是否應該粘在一起。如果它們應該組合在一起,那麼它們必須返回相同的散列碼。

如果您的「浮動」是5天,這意味着必須1/1/2000生成相同的散列碼爲2000年1月4日,2000年1月4日和必須產生相同的散列碼爲1/8/2000年(因爲他們都在5天內彼此)。這意味着1/1/2000具有與1/8/2000相同的代碼(因爲如果a = b且b = c,a = c)。

1/1/2000和2000年1月8日是第5天「浮動」的外部。

+0

非常真實。我想我將不得不放棄使用'GroupJoin'並實現一個允許從左側開始種子的'Comparer'的版本。 –