2016-12-07 33 views
1

我需要比較兩個包含同一類的對象的列表,但不是每個屬性都應該用於檢查差異。例如。不應使用Id(主鍵)屬性。C#在兩個匹配列表中獲得差異

我的例子類:

class MyClass 
{ 
    public System.Nullable<int> Id { get; set; } 
    public int VMId { get; set; } 
    public string Name { get; set; } 
} 

var oldR = new List<MyClass>(); 
oldR.Add(new MyClass() { Id = 1, VMId = 11, Name = "Test1" }); 
oldR.Add(new MyClass() { Id = 2, VMId = 22, Name = "Test2" }); 
oldR.Add(new MyClass() { Id = 3, VMId = 33, Name = "Test3" }); 
oldR.Add(new MyClass() { Id = 4, VMId = 44, Name = "Test4" }); 
oldR.Add(new MyClass() { Id = 5, VMId = 55, Name = "Test5" }); 

var newR = new List<MyClass>(); 
newR.Add(new MyClass() { Id = null, VMId = 22, Name = "Test2" }); 
newR.Add(new MyClass() { Id = null, VMId = 33, Name = "Test3" }); 
newR.Add(new MyClass() { Id = null, VMId = 44, Name = "Test43" }); 
newR.Add(new MyClass() { Id = null, VMId = 55, Name = "Test5" }); 
newR.Add(new MyClass() { Id = null, VMId = 66, Name = "Test6" }); 

我想上述的事情,是兩個列表匹配的VMID財產。接下來,我想檢查Name屬性是否從oldR更改爲newR。

基本上我想現在,Test1應該從數據庫中刪除,Test6應該被添加,並且Test4應該被更新到Test43。

希望它讓SENCE

編輯: 我要指出,我真正的類有+20的屬性。我想現在如何使用linq進行比較,而無需全部指定它們?也許只是排除我不想比較的Id屬性

我該如何做到這一點?

+0

嘗試linq查詢。這可能會幫助你輕鬆地比較對象 –

+0

我應該提及我的真實課程有+20個屬性。我想現在如何使用linq進行比較,而無需全部指定它們?也許只是排除我不想比較的Id屬性 – user1281991

+0

我會使用左外連接來組合列表VMID。看到msdn:https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

回答

2

請看看這個線程implement equatable

這將是重要的,因爲它可以讓你做oldR [I] .Equals(newR)。只需使用一個嵌套的foreach來檢查所有的對象,並吐出一個列表,其中應該刪除哪些項目以及哪些項目應該添加(可以使用removeList和addList來完成)。如果你走linq路線,讓iequatable應該是有用的,linq查詢應該更容易編寫。

3

在C#中有幾種標準的方法來做這種事情。

如果您可以控制正在比較的類,則可以使其實現IEquatable<T>接口,並重載Object.Equals方法以定義如何比較實例。您還應該覆蓋Object.GetHashCode以確保Dictionary s和其他哈希集合的正確工作。

例子:

class MyClass : IEquatable<MyClass> { 

    public string name; 
    public int primaryKey; 

    //IEquatable<T> implementation 
    public bool Equals(MyClass other) => 
     !Equals(other, null) 
     && other.name == this.name; 

    //Overriding Object methods 
    public override bool Equals(object other) => 
     Equals(other as MyClass); 

    public override int GetHashCode() => name.GetHashCode(); 
} 

如果你沒有對這個類的控制,你可以創建一個實現IEqualityComparer<T>接口,可以比較另一個類的實例類。

實施例:

class MyComparer : IEqualityComaprer<MyClass> { 
    public bool Equals(MyClass a, MyClass b) { 
     if (Object.Equals(a, null)) return Object.Equals(b, null); 
     if (Object.Equals(b, null)) return false; 
     return a.name == b.name; 
    } 

    public int GetHashCode(MyClass obj) => obj.name.GetHashCode(); 
} 

許多標準LINQ運營商具有重載受理元件相比IEqualityComparers作爲額外的參數。

+1

請優先' IEqualityComparer <> ** ** always **,並將所需的比較器提供給需要它的函數。通過重寫'Equals()'和'GetHashCode()',您可以更改默認行爲,並且在不同的上下文中使用該類時,這可能會導致意外行爲。 – Oliver

+0

@奧利弗說得很好。 'IEquatable'用於定義該類型的默認比較。不要用它來滿足該類的一個具體用法的需要。對於需要特定非標準比較的情況,「IEqualityComparer」要好得多。 – JamesFaix