2010-08-04 188 views
2

我有什麼似乎是一個常見的問題/模式。同一個對象的兩個集合。該對象有許多屬性和一些嵌套的對象。汽車有一個名爲id的屬性,它是唯一的標識符。比較兩個集合

我想找到LINQ的方式做一個diff,其中包括:在一個收集

  1. 項目,而不是其他(反之亦然)
  2. 對於匹配的項目,是否有任何變化(變化將是所有屬性的比較?(我只在乎可設置的屬性,我會用反射這個?)

回答

10

可以使用Enumerable.Except()方法,這將使用比較器(無論是默認還是一個你提供)來評估哪些對象在bot中^ h序列或只有一個:

var sequenceA = new[] { "a", "e", "i", "o", "u" }; 
var sequenceB = new[] { "a", "b", "c" }; 

var sequenceDiff = sequenceA.Except(sequenceB); 

如果要執行這兩個序列(A-B) union (B-A)的完全脫節,你將不得不使用:

var sequenceDiff = 
     sequenceA.Except(sequenceB).Union(sequenceB.Except(sequenceA)); 

如果你有一個複雜的類型,你可以寫一個IComparer<T>爲您的類型T並使用接受比較器的超載。

對於問題的第二部分,您需要滾動您自己的實現來報告哪些類型的屬性不同。有沒有什麼內置到.NET BCL直接。你必須決定這種報告將採取什麼形式?你如何識別和表達複雜類型的差異?你當然可以使用反射這個...但是如果你只處理單一類型,我會避免這種情況,併爲它寫一個專門的差分實用程序。如果你要支持一系列的類型,那麼反思可能會更有意義。

2

你已經收到了你的上半年的優秀答案。正如LBushkin解釋的那樣,後半部分不能由BCL類直接完成。以下是一個簡單的方法,可以通過所有公共可設置的屬性(注意:在這些情況下,gettor可能不公開!)並逐一比較它們。如果兩個對象100%相等,它將返回true。否則,它會打破早期並返回false:

static bool AllSettablePropertiesEqual<T>(T obj1, T obj2) 
{ 
    PropertyInfo[] info1 = obj1.GetType().GetProperties(
     BindingFlags.Public | 
     BindingFlags.SetProperty | 
     BindingFlags.Instance);  // get public properties 

    PropertyInfo[] info2 = obj2.GetType().GetProperties(
     BindingFlags.Public | 
     BindingFlags.SetProperty | 
     BindingFlags.Instance);  // get public properties 

    // a loop is easier than linq here, and we can break out quick: 
    for (var i = 0; i < info1.Length; i++) 
    { 
     var value1 = info1[i].GetValue(obj1, null); 
     var value2 = info2[i].GetValue(obj2, null) 
     if(value1 == null || value2 ==null) 
     { 
      if(value1 != value2) 
       return false; 
     } 
     else if (!value1.Equals(value2)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

你可以將這個方法很容易地添加到標準LINQ表達式,像這樣:

var reallyReallyEqual = from itemA in listA 
         join itemB in listB 
          on AllSettablePropertiesEqual(itemA, itemB) 
         select itemA; 
+0

的問題是,我想相反。我想要一個基於IEqualityComparer但是具有不同屬性的「相同」項目的列表。我基本上想要所有字段差異的項目列表 – leora 2010-08-05 13:45:39

+0

@ooo:要找到差異,請使用相同的方法,但通過在'AllSettableProperties'前面放置一個'!'來更改連接語句。它返回一個不同的項目列表。爲了找到差異本身,您也可以使用上面的反射示例,只需更改方法以返回具有差異的對的列表。 – Abel 2010-08-05 17:03:14