2009-01-11 32 views
51

這是我正在嘗試做的。我使用LINQ to XML來查詢XML文件,它給了我一個IEnumerable對象,其中T是我的「Village」類,充滿了此查詢的結果。有些結果是重複的,所以我想了IEnumerable對象上執行一個獨特的(),像這樣:C#區別於IEn​​umerable <T>與自定義IEqualityComparer

public IEnumerable<Village> GetAllAlliances() 
{ 
    try 
    { 
     IEnumerable<Village> alliances = 
      from alliance in xmlDoc.Elements("Village") 
      where alliance.Element("AllianceName").Value != String.Empty 
      orderby alliance.Element("AllianceName").Value 
      select new Village 
      { 
       AllianceName = alliance.Element("AllianceName").Value 
      }; 

     // TODO: make it work... 
     return alliances.Distinct(new AllianceComparer()); 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("GetAllAlliances", ex); 
    } 
} 

由於默認的比較不會爲該村對象的工作,我實現了一個自定義的,因爲看到在這裏AllianceComparer類:

public class AllianceComparer : IEqualityComparer<Village> 
{ 
    #region IEqualityComparer<Village> Members 
    bool IEqualityComparer<Village>.Equals(Village x, Village y) 
    { 
     // Check whether the compared objects reference the same data. 
     if (Object.ReferenceEquals(x, y)) 
      return true; 

     // Check whether any of the compared objects is null. 
     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 

     return x.AllianceName == y.AllianceName; 
    } 

    int IEqualityComparer<Village>.GetHashCode(Village obj) 
    { 
     return obj.GetHashCode(); 
    } 
    #endregion 
} 

鮮明的()方法是行不通的,因爲我有相同數量的帶或不帶它的結果。另一件事,我不知道這是否通常是可能的,但我無法進入AllianceComparer.Equals()查看可能存在的問題。
我在互聯網上發現了這個例子,但我似乎無法讓我的實現工作。

希望有人在這裏可能會看到這裏可能是錯的! 在此先感謝!

+0

您的catch/throw構造使調用函數無法再選擇捕獲(ArgumentException)或catch(IOException)(示例)。對於這種情況,您可能最好將try/catch一起移除 - 此外,方法的名稱將成爲異常StackTrace屬性的一部分。 – 2009-12-16 20:22:59

回答

72

問題出在您的GetHashCode。您應該改變它來代替返回AllianceName的哈希碼。

int IEqualityComparer<Village>.GetHashCode(Village obj) 
{ 
    return obj.AllianceName.GetHashCode(); 
} 

的事情是,如果Equals回報true,對象應該具有相同的散列碼這是不是不同Village對象與同一AllianceName的情況。由於Distinct的工作原理是在內部構建一個哈希表,所以最終會得到相同的對象,由於不同的哈希碼,這些對象根本不會匹配。

同樣,要比較兩個文件,如果兩個文件的散列不相同,則根本不需要檢查文件本身。他們是不同的。否則,你會繼續檢查它們是否真的相同。這正是Distinct使用的散列表的行爲。

+0

爲什麼不能重寫Distinct的典型平等方法? – Boog 2013-03-24 01:01:15

+0

@Boog當然,您可以在對象本身或單獨的相等比較器類中執行此操作,如OP所需。自定義相等比較器的用例是當您有不同的方式來考慮對象是否相等時(例如,區分大小寫和不區分大小寫的字符串比較),或者出於某種原因無法更改類本身時。在任何情況下,您都應該覆蓋`Equals`和`GetHashCode`,並針對`Equals`方法編寫正確的`GetHashCode`。 – 2013-03-24 05:54:04

6

或更改線路

return alliances.Distinct(new AllianceComparer()); 

return alliances.Select(v => v.AllianceName).Distinct(); 
10

return alliances.Select(v => v.AllianceName).Distinct();

,將返回的IEnumerable<string>代替IEnumerable<Village>

相關問題