web-dev-qa-db-ja.com

クラスの2つのインスタンスの比較

このようなクラスがあります

_public class TestData
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   
}
_

このクラスのインスタンスを互いに直接比較して、それらがまったく同じであることがわかるかどうかを知りたいですか?メカニズムは何ですか?私はif(testData1 == testData2) //Do Somethingのようなものを探しています。そうでない場合は、どうすればよいですか?

11
Saeid Yazdani

IEquatable<T> クラスのインターフェース。これにより、等価ロジックを定義できます。実際には、Equalsメソッドもオーバーライドする必要があります。

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   

  // Overriding Equals member method, which will call the IEquatable implementation
  // if appropriate.

   public override bool Equals( Object obj )
   {
       var other = obj as TestData;
       if( other == null ) return false;

       return Equals (other);             
   }

   public override int GetHashCode()
   {
      // Provide own implementation
   }


   // This is the method that must be implemented to conform to the 
   // IEquatable contract

   public bool Equals( TestData other )
   {
       if( other == null )
       {
            return false;
       }

       if( ReferenceEquals (this, other) )
       {
            return true;
       }

       // You can also use a specific StringComparer instead of EqualityComparer<string>
       // Check out the specific implementations (StringComparer.CurrentCulture, e.a.).
       if( EqualityComparer<string>.Default.Compare (Name, other.Name) == false )
       {
           return false;
       }
       ...

       // To compare the members array, you could perhaps use the 
       // [SequenceEquals][2] method.  But, be aware that [] {"a", "b"} will not
       // be considerd equal as [] {"b", "a"}

       return true;

   }

}
20

参照タイプTのオブジェクトを相互に比較するには、3つの方法があります。

  1. object.Equals メソッドを使用
  2. IEquatable<T>.Equalsの実装あり(IEquatable<T>を実装する型のみ)
  3. 比較演算子==

さらに、これらの各ケースには2つの可能性があります。

  1. 比較されるオブジェクトの静的タイプはT(またはTの他のベース)
  2. 比較されるオブジェクトの静的タイプはobjectです

絶対に知っておくべきルールは次のとおりです。

  • Equalsoperator==の両方のデフォルトは、参照の等価性をテストすることです
  • Equalsの実装は、比較されるオブジェクトの静的タイプが何であっても正しく機能します
  • IEquatable<T>.Equalsは常にobject.Equalsと同じように動作する必要がありますが、オブジェクトの静的タイプがTの場合、パフォーマンスはわずかに向上します

それで、実際にこれはすべてどういう意味ですか?

経験則として、Equalsを使用して等価性を確認し(必要に応じてobject.Equalsを上書き)、IEquatable<T>も実装して、パフォーマンスをわずかに向上させる必要があります。この場合、object.EqualsIEquatable<T>.Equalsとして実装する必要があります。

特定の型(System.Stringなど)の場合、operator==を使用することもできますが、「多態的な比較」を行わないように注意する必要があります。一方、Equalsメソッドは、そのような比較を行っても正しく機能します。

ポリモーフィック比較の例と、なぜそれが問題になるのか here をご覧ください。

最後に、object.Equalsをオーバーライドする場合は、それに応じてobject.GetHashCodeもオーバーライドする必要があることを忘れないでください。

6
Jon

これを行う1つの方法は、IEquatable<T>を実装することです

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }

   public bool Equals(TestData other)
   {
        if (this.Name != other.Name) return false;
        if (this.type != other.type) return false;

        // TODO: Compare Members and return false if not the same

        return true;
   }
}


if (testData1.Equals(testData2))
    // classes are the same

Equals(object)メソッドを(System.Objectから)オーバーライドすることもできます。これを行う場合は、GetHashCodeもオーバーライドする必要があります ここを参照

5

まず第一に、平等を定義することは困難であり、平等があなたにとって何を意味するかについてあなただけが定義できます

  1. メンバーの価値は同じですか
  2. または、同じ場所を指しています。

ここに議論と答えがあります

参照タイプの2つのインスタンスを比較するための「ベストプラクティス」とは何ですか?

1
user182630

ここには多くの良い答えがありますが、比較を次のように機能させたい場合に備えて

if(testData1 == testData2) // DoSomething

equals関数を使用する代わりに、==および!=演算子をオーバーライドできます。

public static bool operator == (TestData left, TestData right)
{
    bool comparison = true; //Make the desired comparison
    return comparison;
}

public static bool operator != (TestData left, TestData right)
{
    return !(left == right);
}
1
roozbeh S

Equalsメソッドをオーバーライドして、その中で手動でオブジェクトを比較できます

Equals()と演算子== のオーバーロードのガイドラインもご覧ください。

1
Haris Hasan

オブジェクトAをオブジェクトBと等しくするルールを定義してから、このタイプのEquals演算子をオーバーライドする必要があります。

http://msdn.Microsoft.com/en-us/library/ms173147(v = vs.80).aspx

1
DaveRead

IEquatable<T> interfaceを実装します。これは、インスタンスの等価性を判断するための型固有のメソッドを作成するために値型またはクラスが実装する一般化されたメソッドを定義します。詳細はこちら:

http://msdn.Microsoft.com/en-us/library/ms131187.aspx

1
Enigma State