2016-05-04 21 views
1

Wie überprüft man, ob zwei Listen von Objekten gleich sind? Ich habe die Liste A und Liste B mit derselben Struktur:Vergleichen Sie zwei komplexe Listenobjekte

[XmlRoot(ElementName = "Details")] 
public class Details 
{ 
    [XmlElement(ElementName = "time")] 
    public string time { get; set; } 
    [XmlElement(ElementName = "duration")] 
    public string duration { get; set; } 
} 

[XmlRoot(ElementName = "Remark")] 
public class Remark 
{ 
    [XmlElement(ElementName = "RemarkText")] 
    public string RemarkText { get; set; } 
    [XmlElement(ElementName = "isRemarkVisible")] 
    public Boolean IsRemarkVisible { get; set; } 
} 

[XmlRoot(ElementName = "test")] 
public class test 
{ 
    [XmlElement(ElementName = "ID")] 
    public string ID { get; set; } 
    [XmlElement(ElementName = "Name")] 
    public string Name { get; set; } 
    public Details Details { get; set; } 
    [XmlElement(ElementName = "Remark")] 
    public Remark Remark { get; set; } 
} 

[XmlRoot(ElementName = "Tests")] 
public class Tests 
{ 
    [XmlElement(ElementName = "test")] 
    public test[] test { get; set; } 
} 

ich es konvertieren mit Linq aufzulisten.

Liste A:

Test 
id=1 
name=abc 
details 
    starttime=9.00 
    endtime=12.00 
    duration=1hr 
Remark 
    RemarkText= remark1 
    IsRemarkVisible=true 

Liste B:

Test 
id=1 
name=abc 
details 
    starttime=9.00 
    endtime=12.00 
    duration=1hr 
Remark 
    RemarkText= remark2 
    IsRemarkVisible=true 

Hier sind sowohl die Listen sind nicht gleich (remarkText Feld). Ich möchte ein Stück Code, der diese beiden Listen vergleicht und entweder gleich oder nein zurückgibt. Wie kann ich das machen?

Ich versuchte mit List1.Except(List2), aber es vergleicht nicht.

bearbeiten

Ich habe benutzerdefinierte IEqualityComparer erstellt:

public class Compare : IEqualityComparer<test> 
{ 
    public bool Equals(test x, test y) 
    { 
     if (x == null || y == null) return false; 

     bool equals = x.ID == y.ID && x.Name == y.Name && x.Remark == y.Remark 
      && x.Details == y.Details; 
     return equals; 
    } 
    public int GetHashCode(test codeh) 
    { 
     return (codeh.ID + codeh.Name + codeh.Remark + codeh.Details).GetHashCode(); 
    } 
} 

Und

var Comparer = new Compare(); List1.Except(List2, Comparer) Sollte diese Arbeit?

bearbeiten

[XmlRoot(ElementName = "Details")] 
public class Details 
{ 
    [XmlElement(ElementName = "starttime")] 
    public string starttime { get; set; } 
    [XmlElement(ElementName = "endtime")] 
    public string endtime { get; set; } 
    [XmlElement(ElementName = "duration")] 
    public string duration { get; set; } 
} 

[XmlRoot(ElementName = "Remark")] 
public class Remark 
{ 
    [XmlElement(ElementName = "RemarkText")] 
    public string RemarkText { get; set; } 
    [XmlElement(ElementName = "isRemarkVisible")] 
    public Boolean IsRemarkVisible { get; set; } 
} 

[XmlRoot(ElementName = "test")] 
public class test 
{ 
    [XmlElement(ElementName = "ID")] 
    public string ID { get; set; } 
    [XmlElement(ElementName = "Name")] 
    public string Name { get; set; } 
    public Details Details { get; set; } 
    [XmlElement(ElementName = "Remark")] 
    public Remark Remark { get; set; } 
    [XmlElement(ElementName = "Tags")] 
    public Tags Tags { get; set; } 
} 

[XmlRoot(ElementName = "Tags")] 
public class Tags 
{ 
    [XmlElement(ElementName = "TagLocation")] 
    public TagLocation[] TagLocation { get; set; } 
} 

[XmlRoot(ElementName = "TagLocation")] 
public class TagLocation 
{ 
    [XmlElement(ElementName = "Id")] 
    public string Id { get; set; } 
    [XmlElement(ElementName = "TagText")] 
    public string TagText { get; set; } 
} 

[XmlRoot(ElementName = "Tests")] 
public class Tests 
{ 
    [XmlElement(ElementName = "test")] 
    public test[] test { get; set; } 
} 
+0

Wann sind zwei Objekte gleich? Im Allgemeinen implementieren Sie einen benutzerdefinierten IEqualityComparer und übergeben Sie es an außer. –

+0

Wenn beide Objekte die gleichen Daten haben. In meinem Beispiel, wenn Liste B hatte remarkText = Bemerkung1 – Arti

+0

@TimSchmelter Würden Sie bitte ein Beispiel geben, wie es zu tun ist. – Arti

Antwort

2

zuerst Ihre test Klasse ändern und implementieren (überschreiben), um die Equals Funktion. Dies gibt der Klasse die Möglichkeit, sich mit einem anderen Objekt zu vergleichen und festzustellen, ob beide gleich sind oder nicht.

Idealerweise sollte jede Klasse Ihre eigene Equals -Implementierung haben, und die Elternklasse sollte keine Aufgabe haben, die Interna von untergeordneten Objekten zu vergleichen. Aber da Sie nur Ihre test Klasse vergleichen müssen, implementieren wir die gesamte Vergleichslogik in der Klasse test.

[XmlRoot(ElementName = "test")] 
public class test 
{ 
    [XmlElement(ElementName = "ID")] 
    public string ID { get; set; } 
    [XmlElement(ElementName = "Name")] 
    public string Name { get; set; } 
    public Details Details { get; set; } 
    [XmlElement(ElementName = "Remark")] 
    public Remark Remark { get; set; } 
    [XmlElement(ElementName = "Tags")] 
    public Tags Tags { get; set; } 

    // override object.Equals 
    public override bool Equals(object obj) 
    { 
     if (obj == null || GetType() != obj.GetType()) return false; 

     // modify the code below to suit your needs... 
     test objA = (test)obj; 
     if (
       this.ID != objA.ID || this.Name != objA.Name 
       || this.Details.duration != objA.Details.duration || this.Details.starttime != objA.Details.starttime || this.Details.endtime != objA.Details.endtime 
       || this.Remark.IsRemarkVisible != objA.Remark.IsRemarkVisible || this.Remark.RemarkText != objA.Remark.RemarkText 
      ) return false; 
     if (this.Tags.TagLocation.Length != objA.Tags.TagLocation.Length) return false; 
     for (int i = 0; i < this.Tags.TagLocation.Length; i++) 
     { 
      if (this.Tags.TagLocation[i].Id != objA.Tags.TagLocation[i].Id || this.Tags.TagLocation[i].TagText != objA.Tags.TagLocation[i].TagText) return false; 
     } 
     return true; // if everything matched we infer that the objects are equal. 
    } 

    // override object.GetHashCode 
    public override int GetHashCode() 
    { 
     // modify the code below to generate a unique hash code for your object. 
     return base.GetHashCode(); 
    } 
} 

Dann können Sie problemlos zwei Objekte Ihrer Testklasse einfach vergleichen.

z.B.

private void button1_Click(object sender, EventArgs e) 
{ 

    test test1, test2, test3; 

    test1 = new test { ID="1", Name ="abc"}; 
    test1.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" }; 
    test1.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark1" }; 
    test1.Tags = new Tags(); 
    test1.Tags.TagLocation = new TagLocation[] 
    { 
     new TagLocation{ Id = "1", TagText = "tag1" }, 
     new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    test2 = new test { ID = "1", Name = "abc" }; 
    test2.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" }; 
    test2.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark2" }; 
    test2.Tags = new Tags(); 
    test2.Tags.TagLocation = new TagLocation[] 
    { 
     new TagLocation{ Id = "1", TagText = "tag1" }, 
     new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    test3 = new test { ID = "1", Name = "abc" }; 
    test3.Details = new Details { duration = "1", starttime = "9.00", endtime = "12.00" }; 
    test3.Remark = new Remark { IsRemarkVisible = true, RemarkText = "remark2" }; 
    test3.Tags = new Tags(); 
    test3.Tags.TagLocation = new TagLocation[] 
    { 
     new TagLocation{ Id = "1", TagText = "tag1" }, 
     new TagLocation{ Id = "2", TagText = "tag2" } 
    }; 

    MessageBox.Show("test1.Equals(test2) ... " + test1.Equals(test2).ToString()); // shows false 
    MessageBox.Show("test2.Equals(test3) ... " + test2.Equals(test3).ToString()); // shows true 
} 
+0

Benötige ich noch IEqualityComparer? – Arti

+0

Nein, das tust du nicht. Sie haben nun eine Methode in Ihrer Klasse namens "Equals", mit der Sie zwei Objekte Ihrer Klasse vergleichen können. –

+0

Ich habe edit mein Klassenobjekt, um eine dritte Ebene zur Klasse zu haben. Wie würde es dann anders sein? – Arti

0

Ihr Problem ist, dass die inneren Klassen Gleichheitsoperator Überlastungen nicht == haben.

gibt zum Beispiel x.Details == y.Details immer false, unabhängig davon, welche Daten der Instanzen halten, da der Standard == Operator nur die Methode Equals aufruft, die in einer Referenz Gleichheit führt, wie in object.Equals Methode definiert.

Siehe Guidelines for Overloading Equals() and Operator == (C# Programming Guide)

Außerdem gibt es einen Fehler in GetHashCode-Methode. Berechnen Sie die Hash-Codes niemals mit String-Verkettung.Darüber hinaus überladen Sie nicht die ToString-Methode, so dass es nur die gleiche Standardzeichenfolge zurückgibt, die für die Hash-Code-Berechnung nicht nützlich ist.