2016-05-04 5 views
1

2つのオブジェクトのリストが同じかどうかを確認する方法?私は同じ構造のリストAとリストBを持っています:2つの複合リストオブジェクトを比較する

[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; } 
} 

linqを使ってリストに変換します。

リストA:

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

リストB:

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

ここでは、両方のリストは、(remarkTextフィールド)と同じではありません。私は、これらの2つのリストを比較し、同じか否かを返すコードを必要とします。どうやってやるの?

List1.Except(List2)を使ってみましたが、比較しません。

編集

私はカスタムされたIEqualityComparer作成しました:

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

そして

var Comparer = new Compare(); List1.Except(List2, Comparer)万一この作品?

編集

[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

2つのオブジェクトが等しいのはいつですか?一般的にカスタム 'IEqualityComparer 'を実装し、それを 'Except'に渡します。 –

+0

両方のオブジェクトに同じデータがある場合。私の例ではリストBがあった場合remarkText = remark1 – Arti

+0

@TimSchmelterあなたはどのようにしなければならないかの例を教えてください。 – Arti

答えて

2

まず、あなたのtestクラスを変更し、(オーバーライド)Equals機能を実装しています。これにより、クラス自体が別のオブジェクトと比較して、両方が同じかどうかを判断できるようになります。

理想的には、クラスのそれぞれにEquals実装があり、親クラスは子オブジェクトの内部を比較する必要がありません。しかし、testクラスだけを比較する必要があることを見て、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(); 
    } 
} 

次に、テストクラスの2つのオブジェクトを簡単に比較できます。

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

私はまだIEqualityComparerが必要ですか? – Arti

+0

いいえ、そうではありません。あなたはクラスに 'Equals'という名前のメソッドを持っています。クラスの2つのオブジェクトを比較するのに使うことができます。 –

+0

クラスオブジェクトを編集して、3番目のレベルのクラスを作成しました。どのようにそれは異なっていますか? – Arti

0

問題は、内部クラスに等価演算子オーバーロード==がないことです。例えば

object.Equals

方法で定義されているデフォルト==オペレータは単に、基準等価になるEqualsメソッドを呼び出すため、x.Details == y.Detailsは常に関係なくインスタンスが保持するデータ、falseを返しません。

は、GetHashCodeメソッドにエラーがある、また

Guidelines for Overloading Equals() and Operator == (C# Programming Guide)を参照してください。文字列連結でハッシュコードを決して計算しないでください。さらに、ToStringメソッドがオーバーロードされないので、ハッシュコードの計算には役立たない同じデフォルトの文字列が返されます。

関連する問題