LINQの2つのクラスを比較する - 「ミスマッチ」を取得する

私は次のクラスを持っています:

public class DocumentCompare
{
    public string Customer;
    public string Filename;
    public string Reference;
    public DateTime? Date;

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        DocumentCompare doc = obj as DocumentCompare;
        if ((Object)doc == null)
            return false;

        return (doc.Customer == Customer) && (doc.Date == Date) && (doc.Filename == Filename) && (doc.Reference == Reference);
    }

    public bool Equals(DocumentCompare doc)
    {
        if ((object)doc == null)
            return false;

        return (doc.Customer == Customer) && (doc.Date == Date) && (doc.Filename == Filename) && (doc.Reference == Reference);
    }

    public override int GetHashCode()
    {
        return string.Format("{0}_{1}_{2}_{3}",Customer,Filename,Reference,(Date == null ? "" : Date.Value.ToString())).GetHashCode();
    }
}

私はこのクラスの2つのリストを取得します - 私がしたいのは、2つを比較し、両方に存在しないものを取得することです。したがって、アイテムがxリストに存在し、yに存在しない場合、このリスト内のアイテムに対してアクションを実行したいと思います。アイテムがyリストに存在するがxに存在しない場合、別のアクションを実行したい。

どうすればいい? LINQを使うと思います!

編集:パフォーマンスはあまり問題にはならない - これは1回だけ実行されます

1

3 答え

例外 だけが必要なようです:

foreach (var newItem in firstList.Except(secondList))
{
    ...
}

余談として:

  • これは、ハッシュコードを生成するための素晴らしい方法ではありません。ここで他の質問を検索してください。
  • 繰り返し論理を避けるために Equals(object)から Equals(DocumentCompare)に委譲する
  • 変更可能な型は、等価比較のための大きな候補ではありません(特に、辞書でキーとして値を使用した場合、等価性の高いコンポーネントを変更した場合、キーを再度見つけることができなくなります) )
  • 変更可能にしたい場合でも、プロパティはカプセル化の方がパブリックフィールドより優れています。
  • タイプを封印するか、2つのオブジェクトが同じタイプのものかどうかをチェックします。そうでないと、非対称の平等に終わる可能性があります。
5
追加された
ありがとう - 私はそれが最高の解決策ではないことを知っていますが、これは一度だけ実行されます
追加された 著者 Chris,
+1強く同意する3:通常、デフォルトの参照平等をそのままにするか、代理キーを導入し、絶対に必要な場合はそれを比較するのが最良です
追加された 著者 MattDavey,

このメソッドを使用して、2つの異なるリストのオブジェクトを比較できます。 exmp:リストとリストxとy = DocumentCompare、

  public static bool EqualsObject(this T t1, T t2) where T : class
        {
            var p1 = t1.GetType().Fields();
            var p2 = t2.GetType().Fields();
            for (int j = 0; j < p1.Length; j++)
            {
                var x = p1[j].GetValue(t1, null);
                var y = p2[j].GetValue(t2, null);
                if (x == null && y == null)
                    continue;
                if (x != null && y == null)
                    return false;
                if (x == null)
                    return false;
                if (!x.Equals(y))
                {
                    return false;
                }
            }
            return true;
        }

このメソッドは、これら2つのリストの違いを表示します。

    public static List DifferentObjects(List t, List t2) where T : class
    {
        var diff = new List();
        if (t != null && t2 != null)
        {
            foreach (T t1 in t)
            {
                var state = false;
                foreach (T t3 in t2.Where(t3 => EqualsObject(t1,t3)))
                {
                    state = true;
                }
                if (!state)
                {
                    diff.Add(t1);
                }
            }
        }
        return diff;
    }

この方法でコードを使用することができます

        var t = new List();
        var t2 = new List();

        t.Add(new DocumentCompare{Customer = "x"});
        t.Add(new DocumentCompare{Customer = "y"});
        t.Add(new DocumentCompare{Customer = "z"});

        t2.Add(new DocumentCompare { Customer = "t" });
        t2.Add(new DocumentCompare { Customer = "y" });
        t2.Add(new DocumentCompare { Customer = "z" });

        var list = DifferentObjects(t, t2);
        var list2 = DifferentObjects(t2, t);

あなたのクラスでフィールド(Customer、FileNameなど)を使用したので、GetType()。Fields(); EqualsObjectメソッドで使用されます。プロパティを使用する場合は、GetType()を使用する必要があります。 EqualsObjectメソッドで宣言します。

0
追加された

ここにコードです:

var elementsMissingFromFirstList = firstList.Except(secondList).ToList();
var elementsMissingInSecondList  = secondList.Except(firstList).ToList();

今あなたはこれらの欠けている要素にあなたの行動を実行することができます:)

0
追加された