2016-12-07 6 views
1

Ich muss zwei Listen vergleichen, die Objekte der gleichen Klasse enthalten, aber nicht jede Eigenschaft sollte verwendet werden, um auf Unterschiede zu prüfen. Z.B. Die Id-Eigenschaft (Primärschlüssel) sollte nicht verwendet werden.C# bekomme Unterschiede in zwei übereinstimmenden Listen

Mein Beispiel Klasse:

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" }); 

Was ich mit dem oben tun möchte, ist, die beiden Listen auf der vmid Eigenschaft übereinstimmen. Als nächstes möchte ich prüfen, ob sich die Name-Eigenschaft von oldR zu newR geändert hat.

Grundsätzlich möchte ich jetzt, dass Test1 aus der Datenbank entfernt werden sollte, Test6 sollte hinzugefügt werden, und Test4 sollte auf Test43 aktualisiert werden.

Hoffe, es macht Sinn

EDIT: sollte ich erwähnen, dass meine wirkliche Klasse 20 Eigenschaften hat. Ich möchte jetzt wie man Linq verwenden, um zu vergleichen, ohne sie alle zu spezifizieren? Und vielleicht nur die Id-Eigenschaft ausschließen, die ich nicht vergleichen möchte

Wie kann ich das erreichen?

+0

Versuchen Sie linq Abfragen. Das kann Ihnen helfen, die Objekte leicht zu vergleichen –

+0

Ich sollte erwähnen, dass meine echte Klasse +20 Eigenschaften hat. Ich möchte jetzt wie man Linq verwenden, um zu vergleichen, ohne sie alle zu spezifizieren? Und vielleicht nur die Id-Eigenschaft ausschließen, die ich nicht vergleichen möchte – user1281991

+0

Ich würde einen linken äußeren Join verwenden, um Listen VMID zu kombinieren. Siehe msdn: https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

Antwort

2

Bitte schauen Sie in diesen Thread implement equatable

dies wichtig sein wird, weil es Ihnen oldR tun können [i] .Equals (newr). Verwenden Sie einfach eine verschachtelte foreach, die alle Objekte überprüft und eine Liste ausgibt, welche Objekte entfernt werden sollen und welche hinzugefügt werden sollen (Sie könnten dies mit removeList und addList tun). Wenn Sie die Linq-Route gehen, sollte die icequatable nützlich sein und die linq-Abfrage sollte einfacher zu schreiben sein.

3

Es gibt einige Standardmethoden, um diese Art von Sache in C# zu machen.

Wenn Sie die zu vergleichende Klasse steuern können, können Sie die Schnittstelle IEquatable<T> implementieren und die Methode Object.Equals überladen, um zu definieren, wie Instanzen verglichen werden. Sie sollten auch Object.GetHashCode überschreiben, um sicherzustellen, dass die Gleichheit in Dictionary s und anderen Hash-Sammlungen ordnungsgemäß funktioniert.

Beispiel:

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(); 
} 

Wenn Sie die Kontrolle über diese Klasse nicht haben, können Sie eine Klasse erstellen, die die IEqualityComparer<T>-Schnittstelle implementiert, die Instanzen einer anderen Klasse vergleichen.

Beispiel:

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(); 
} 

Viele der Standard-LINQ-Operatoren haben Überlastungen IEqualityComparers als zusätzliche Parameter für Element Vergleich zu akzeptieren.

+1

Bitte lieber ' IEqualityComparer <> '** immer ** und stellen Sie den gewünschten Vergleich zu der Funktion, wo Sie es brauchen.Durch Überschreiben von 'Equals()' und 'GetHashCode()' ändern Sie das Standardverhalten und dies kann zu unerwartetem Verhalten führen, wenn Sie die Klasse in einem anderen Kontext verwenden. – Oliver

+0

@Oliver macht einen guten Punkt. 'IEquatable' soll den Standardvergleich für diesen Typ definieren. Verwenden Sie es nicht, um die Anforderungen nur einer spezifischen Verwendung dieser Klasse zu erfüllen. 'IEqualityComparer' ist viel besser für Situationen, die einen bestimmten Nicht-Standard-Vergleich benötigen. – JamesFaix

Verwandte Themen