2012-02-06 67 views
1

我有以下類:兩個班在LINQ比較 - 讓「錯配」

public class DocumentCompare 
{ 
    public string Customer; 
    public string Filename; 
    public string Reference; 
    public DateTime? Date; 

    public override bool Equals(object obj) 
    { 
     if (obj == null) 
      return false; 

     DocumentCompare doc = obj as DocumentCompare; 
     if ((Object)doc == null) 
      return false; 

     return (doc.Customer == Customer) && (doc.Date == Date) && (doc.Filename == Filename) && (doc.Reference == Reference); 
    } 

    public bool Equals(DocumentCompare doc) 
    { 
     if ((object)doc == null) 
      return false; 

     return (doc.Customer == Customer) && (doc.Date == Date) && (doc.Filename == Filename) && (doc.Reference == Reference); 
    } 

    public override int GetHashCode() 
    { 
     return string.Format("{0}_{1}_{2}_{3}",Customer,Filename,Reference,(Date == null ? "" : Date.Value.ToString())).GetHashCode(); 
    } 
} 

我會抓取這個類的2只列出了 - 我想要做的就是兩者進行比較,並獲得那些這兩者都不存在。所以如果一個項目存在於x列表中但不存在於y中,我想對這個列表中的項目執行一個動作。如果一個項目存在於y列表中但不存在於x中,我想要執行不同的操作。

我該怎麼做?我猜是使用LINQ!

編輯:性能不是大問題 - 這將只運行一次

回答

5

這聽起來像你只是想Except

foreach (var newItem in firstList.Except(secondList)) 
{ 
    ... 
} 

順便說一句:

  • 這不是生成哈希碼的非常好的方法 - 在這裏搜索其他問題。
  • 代表從Equals(object)Equals(DocumentCompare)避免重複的邏輯
  • 可變類型不是平等的比較巨大的候選人(尤其是一個你已經使用的值作爲字典的關鍵,如果你改變了平等敏感你將無法找到再次鍵)
  • 即使你希望它是可變的,性質是封裝比公共領域
  • 我要麼密封類型或檢驗兩者是否更好的組件對象是,確切的說是是同一類型,否則你可能會以asymm結尾etric平等
+0

+1非常同意拋開3:通常最好保留默認的引用等式,或者引入代理鍵,並且如果您絕對必須進行比較 – MattDavey 2012-02-06 09:44:41

+1

謝謝 - 我知道這不是最好的解決方案,但這隻會運行一次 – Chris 2012-02-07 08:29:47

0

這裏是代碼:

var elementsMissingFromFirstList = firstList.Except(secondList).ToList(); 
var elementsMissingInSecondList = secondList.Except(firstList).ToList(); 

現在你可以在這些缺失的元素進行您的行爲:)

0

您可以使用此方法來比較兩個不同的列表的對象。 exmp:列表和列表x和y = DocumentCompare,

public static bool EqualsObject<T>(this T t1, T t2) where T : class 
     { 
      var p1 = t1.GetType().Fields(); 
      var p2 = t2.GetType().Fields(); 
      for (int j = 0; j < p1.Length; j++) 
      { 
       var x = p1[j].GetValue(t1, null); 
       var y = p2[j].GetValue(t2, null); 
       if (x == null && y == null) 
        continue; 
       if (x != null && y == null) 
        return false; 
       if (x == null) 
        return false; 
       if (!x.Equals(y)) 
       { 
        return false; 
       } 
      } 
      return true; 
     } 

此方法將顯示這兩個列表之間的區別。

public static List<T> DifferentObjects<T>(List<T> t, List<T> t2) where T : class 
    { 
     var diff = new List<T>(); 
     if (t != null && t2 != null) 
     { 
      foreach (T t1 in t) 
      { 
       var state = false; 
       foreach (T t3 in t2.Where(t3 => EqualsObject(t1,t3))) 
       { 
        state = true; 
       } 
       if (!state) 
       { 
        diff.Add(t1); 
       } 
      } 
     } 
     return diff; 
    } 

你可以使用這樣的代碼

 var t = new List<DocumentCompare>(); 
     var t2 = new List<DocumentCompare>(); 

     t.Add(new DocumentCompare{Customer = "x"}); 
     t.Add(new DocumentCompare{Customer = "y"}); 
     t.Add(new DocumentCompare{Customer = "z"}); 

     t2.Add(new DocumentCompare { Customer = "t" }); 
     t2.Add(new DocumentCompare { Customer = "y" }); 
     t2.Add(new DocumentCompare { Customer = "z" }); 

     var list = DifferentObjects(t, t2); 
     var list2 = DifferentObjects(t2, t); 

你在課堂上使用的字段(客戶,文件名等),這樣的GetType()場()。在EqualsObject方法中使用。如果你使用屬性,你應該使用GetType()。Properties();在EqualsObject方法中。