モルモルしている

最近はテスト業務ばっかりで書くことがない

自作クラスのリストを比較する

単純にListの内容を比較したかったのだがSequenceEqualでは比較ができなかった。
まったく同じデータが入っているのになぜfalseになるのだ、と思って調べたら同じデータが入っていても「含まれているオブジェクトの参照が異なるため等価とみなされません」のだそうだ。
Enumerable.SequenceEqual(TSource) メソッド (IEnumerable(TSource), IEnumerable(TSource)) (System.Linq)

「シーケンス内のオブジェクトの参照ではなく実際のデータを比較する場合は、IEqualityComparer ジェネリック インターフェイスをクラスで実装する必要があります。」ということなので、実装した。
※↑のリンク先でも実装方法が説明されているけど、それに従っても比較ができない。
 ↓のやり方が有効。これに気づくまでに二時間かかって悲しかった。
Enumerable.SequenceEqual(TSource) メソッド (IEnumerable(TSource), IEnumerable(TSource), IEqualityComparer(TSource)) (System.Linq)

public class SampleClass
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class CompareSample : IEqualityComparer<SampleClass>
{
    public bool Equals(SampleClass x, SampleClass y)
    {
        if (Object.ReferenceEquals(x, y)) return true;

        return x != null && y != null && x.Id.Equals(y.Id) && x.Name.Equals(y.Name);
    }

    public int GetHashCode(SampleClass obj)
    {
        int hashId = obj.Id.GetHashCode();
        int hashName = obj.Name == null ? 0 : obj.Name.GetHashCode();

        return hashId ^ hashName;
    }
}

public class Main
{
    var sample1 = new List<SampleClass> { new SampleClass { Id = 1, Name = "Yamada" } };
    var sample2 = new List<SampleClass> { new SampleClass { Id = 1, Name = "Yamada" } };

    // 普通にやるとfalseが返る
    bool result = sample1.SequenceEqual(sample2);
    // SequenceEqualに上で作ったCompareSampleを指定してやるとデータが比較されてtrueが返る
    bool result = sample1.SequenceEqual(sample2, new CompareSample());
}