3

2 つのリストが等しいかどうかを比較できるメソッドを作成しようとしています。あるリストのすべての要素が別のリストのすべての要素と同じ値であることを検証する方法でそれらを比較しようとしています。以下の私のEqualsメソッドは常に を返しますがfalse、その理由は誰にも分かりますか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class IEnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        for(int i = 0; i<x.Count();i++){
          if(!Object.Equals(x.ElementAt(i), y.ElementAt(i))){
             return false;
          }
        }
        return true;
    }

    public int GetHashCode(IEnumerable<T> obj)
    {
        if (obj == null)
            return 0;

        return unchecked(obj
            .Select(e => e.GetHashCode())
            .Aggregate(0, (a, b) => a + b)); 
    }
}

このEquals方法をテストするために使用しているデータは次のとおりです。

 static void Main(string[] args)
        {
            Car car1 = new Car();
            car1.make = "Toyota";
            car1.model = "xB";

            Car car2 = new Car();
            car2.make = "Toyota";
            car2.model = "xB";

            List<Car> l1 = new List<Car>();
            List<Car> l2 = new List<Car>();
            l1.Add(car1);
            l2.Add(car2);

           IEnumerableComparer<Car> seq = new IEnumerableComparer<Car>();

           bool b = seq.Equals(l1, l2);

           Console.Write(b); //always says false
           Console.Read();
        }
    }

車のクラス:

   class Car
    {
        public String make { get; set; }
        public String model { get; set; }
    }
4

3 に答える 3

5

Equals参照の比較 (参照型の場合)の既定のバージョン。この問題には、次の 3 つの解決策が考えられます。

  • オーバーライドEqualsとクラスGetHashCode_Car

  • 個々のインスタンスを比較し、ユースケースごとにその実装を提供するために使用される別のバージョンのIEnumerableComparer<T>コンストラクターを追加しますIEqualityComparer<T>

  • 値型のみを使用してください。それらについては、 のデフォルト バージョンがEquals期待どおりに動作します。これらの値型のすべてのフィールドとプロパティは、ここで指定された 1 番目または 3 番目のオプションに準拠する必要があることに注意してください (つまりEqualsGetHashCodeオーバーライドされているか、値型でもある)。これは一般的に推奨される解決策ではありません。理論的な可能性として言及しただけです。あなたの場合、それは役に立ちます - に変更class Carしてみてくださいstruct Car

また、wageoghe の回答で正しく指摘されているようSequenceEqualに、独自の実装を作成する代わりにメソッドを使用できますが、上記の解決策のいずれかに準拠する必要があります ( SequenceEqual2 番目のオプションにこのオーバーロードを使用)。

于 2013-11-09T21:39:50.777 に答える
2

何かが足りないのかもしれませんが、SequenceEqual を使用しないのはなぜですか?

http://msdn.microsoft.com/en-us/library/bb348567(v=vs.110).aspx

Bool b = l1.SequenceEqual(l2);

シーケンス内のオブジェクトは、Equals と GetHashCode を正しく実装する必要があることに注意してください。

于 2013-11-09T21:42:22.657 に答える
1

あなたの車にもオーバーライドを与えてください:

class Car
{
    public String make { get; set; }
    public String model { get; set; }
    public override bool Equals(object obj)
    {
        var other = obj as Car;
        return (other != null) 
                && (this.make == other.make) 
                && (this.model == other.model); 
    }
    public override int GetHashCode()
    {
        return make.GetHashCode() ^ model.GetHashCode();
    }
}
于 2013-11-09T22:06:25.857 に答える