2016-10-04 77 views
7

我正在使用Enumerable.Union<TSource>方法獲取自定義List1與自定義List2的聯合。但不知何故,它不適用於我的情況。我得到所有的項目也重複一次。如何使用C#LINQ Union獲取自定義list1與列表2的聯合

我跟着MSDN Link完成工作,但仍然無法達到同樣的效果。

以下是自定義類的代碼: -

public class CustomFormat : IEqualityComparer<CustomFormat> 
{ 
    private string mask; 

    public string Mask 
    { 
     get { return mask; } 
     set { mask = value; } 
    } 

    private int type;//0 for Default 1 for userdefined 

    public int Type 
    { 
     get { return type; } 
     set { type = value; } 
    } 
    public CustomFormat(string c_maskin, int c_type) 
    { 
     mask = c_maskin; 
     type = c_type; 
    } 

    public bool Equals(CustomFormat x, CustomFormat y) 
    { 
     if (ReferenceEquals(x, y)) return true; 

     //Check whether the products' properties are equal. 
     return x != null && y != null && x.Mask.Equals(y.Mask) && x.Type.Equals(y.Type); 
    } 

    public int GetHashCode(CustomFormat obj) 
    { 
     //Get hash code for the Name field if it is not null. 
     int hashProductName = obj.Mask == null ? 0 : obj.Mask.GetHashCode(); 

     //Get hash code for the Code field. 
     int hashProductCode = obj.Type.GetHashCode(); 

     //Calculate the hash code for the product. 
     return hashProductName^hashProductCode; 
    } 
} 

此,我呼籲如下: -

List<CustomFormat> l1 = new List<CustomFormat>(); 
l1.Add(new CustomFormat("#",1)); 
l1.Add(new CustomFormat("##",1)); 
l1.Add(new CustomFormat("###",1)); 
l1.Add(new CustomFormat("####",1)); 

List<CustomFormat> l2 = new List<CustomFormat>(); 
l2.Add(new CustomFormat("#",1)); 
l2.Add(new CustomFormat("##",1)); 
l2.Add(new CustomFormat("###",1)); 
l2.Add(new CustomFormat("####",1)); 
l2.Add(new CustomFormat("## ###.0",1)); 

l1 = l1.Union(l2).ToList(); 

foreach(var l3 in l1) 
{ 
    Console.WriteLine(l3.Mask + " " + l3.Type); 
} 

請建議合適的方式來達到同樣的!

+3

看起來很奇怪,但是如果你a)爲CustomFormat提供了一個無參數的構造函數,並將該類的一個實例傳遞給了Union方法 - 請參閱https://dotnetfiddle.net/YTVwTI。那麼問題在於,爲什麼Union在類中忽略了IEqualityComparer 的實現。 – stuartd

回答

8

這裏的奇怪之處在於你的班級實施IEqualityComparer<CustomClass>而不是IEquatable<CustomClass>。您可能通過CustomClass的另一個實例,將用作比較器,但更簡單的做法是使CustomClass實施IEquatable<CustomClass>,並覆蓋Equals(object)

IEquatable<T>IEqualityComparer<T>之間的區別是,IEquatable<T>說:「我知道如何用自己的T另一個實例進行比較」,而IEqualityComparer<T>說:「我知道該怎麼兩個實例比較T」。後者通常單獨提供 - 就像通過另一個參數可以提供給Union一樣。一種類型爲其自己的類型實現IEqualityComparer<T>是非常罕見的 - 而IEquatable<T>應該差不多只有用於比較相同類型的值。

下面是一個使用自動實現的屬性來實現簡單性和更多慣用參數名稱的實現。我可能會自己更改散列代碼實現並使用表達式成員,但這是另一回事。

public class CustomFormat : IEquatable<CustomFormat> 
{ 
    public string Mask { get; set; } 
    public int Type { get; set; } 

    public CustomFormat(string mask, int type) 
    { 
     Mask = mask; 
     Type = type; 
    } 

    public bool Equals(CustomFormat other) 
    { 
     if (ReferenceEquals(this, other)) 
     { 
      return true; 
     } 
     return other != null && other.Mask == Mask && other.Type == Type; 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as CustomFormat); 
    } 

    public override int GetHashCode() 
    { 
     // Get hash code for the Name field if it is not null. 
     int hashProductName = Mask == null ? 0 : Mask.GetHashCode(); 

     //Get hash code for the Code field. 
     int hashProductCode = Type.GetHashCode(); 

     //Calculate the hash code for the product. 
     return hashProductName^hashProductCode; 
    } 
} 

現在沒有幫助,(如在評論中所指出)爲Enumerable.Union文件是錯誤的。目前,它規定:

默認的相等比較,Default,用於比較實現了IEqualityComparer<T>通用接口類型的值。

應該這樣說:

默認的相等比較,Default,使用時未提供具體IEqualityComparer<T>來比較值。如果T執行IEquatable<T>,則默認比較器將使用該實現。否則,它將使用執行Equals(object)

+0

我嘗試過實施,但似乎沒有解決問題。請參閱代碼[鏈接](https://dotnetfiddle.net/YTVwTI)。它顯示沒有錯誤,但顯示重複的項目。 – JDoshi

+0

@JDoshi:那個小提琴仍然實現'IEqualityComparer '。我給出的代碼(實現'IEquatable '而不是*)可以和你給出的例子一起工作。 –

+0

其實我是在同一個小提琴中編輯的,並分享了由stuartd共同分享的鏈接。所以你意外地分享了錯誤的小提琴。對不起:( – JDoshi

3

您需要將IEqualityComparer的實例傳遞給Union方法。該方法有一個重載傳入你的比較器。

的最簡單和最醜陋的解決方案是

var comparer = new CustomFormat(null,0); 

l1 = l1.Union(l2, comparer).ToList(); 

您已經在執行犯了一些錯誤。您不應該在您的類型(CustomFormat)上實施IEqualityComparer方法,而應在單獨的課程上執行此方法,如CustomFormatComparer

在您的類型(CustomFormat)上,您應該執行IEquatable

+4

聯合的MSDN鏈接是誤導,然後,因爲它說_「默認的相等比較器,默認,用於比較類型的值實現IEqualityComparer通用接口。**要比較自定義數據類型,您需要來實現這個接口併爲類型**提供你自己的GetHashCode和Equals方法。「_它沒有規定這必須在一個單獨的類中。 – stuartd

+0

@Jehof您能否在這種情況下請說明使用'IEquatable'。這裏直接執行'IEquatable',而不是'IEqualityComparer'在使用'Union'後出錯。 – JDoshi

+0

@JDoshi:不,它不是 - 執行'IEquatable '真的是在這裏前進的道路。 –