Object.Equals メソッド (Object)

2013/12/12

指定した Object が、現在の Object と等しいかどうかを判断します。

Namespace:  System
アセンブリ:  mscorlib (mscorlib.dll 内)

public virtual bool Equals(
	Object obj
)

パラメーター

obj
型: System.Object
現在の Object と比較する Object

戻り値

型: System.Boolean
指定された Object が現在の Object と同じである場合は true、異なる場合は false

Equals の既定の実装では、参照型については参照の等価、値の型についてはビットごとの等価をサポートします。参照の等価とは、比較されるオブジェクト参照が同じオブジェクトを参照していることを意味します。ビットごとの等価とは、比較されるオブジェクトのバイナリ表現が同じであることを意味します。

値の等価を実装するために、派生型によって Equals メソッドがオーバーライドされる場合があることに注意してください。値の等価とは、比較されるオブジェクトのバイナリ表現が異なっていても、同じ値を持つことを意味します。たとえば、Decimal オブジェクトが 2 つあり、それぞれ 1.10 と 1.1000 という数値を表すとします。この Decimal オブジェクトは、末尾の 0 の数が異なることからバイナリ表現が異なり、ビットごとの等価ではありません。しかし、比較する上では末尾の 0 は重要でなく、1.10 と 1.1000 は同一であると見なされるため、オブジェクトは値の等価となります。

実装時の注意

このメソッドは、派生クラスでオーバーライドできます。たとえば、両方のオブジェクトが同じ値を参照している場合、基本データ型は true を返します。それ以外の場合は false を返します。

このメソッドは、プリミティブとオブジェクトだけを比較します。オブジェクト配列などの複雑な構造体を比較するには、このメソッドをオーバーライドする必要があります。

次に示すステートメントは、Equals メソッドのすべての実装に対し true である必要があります。リストの x、y、および z は、null 以外のオブジェクト参照を表します。

  • x.Equals(x) は、浮動小数点型が関連する場合を除き、true を返します。IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems を参照してください。

  • x.Equals(y) は y.Equals(x) と同じ値を戻します。

  • x.Equals(y) は、x と y が両方とも NaN である場合に true を返します。

  • (x.Equals(y) && y.Equals(z)) が true を返す場合、x.Equals(z) は true を返します。

  • x.Equals(y) を連続して呼び出す場合、x と y が参照するオブジェクトが変更されていない限り、同じ値が返されます。

  • x.Equals(null) は false を返します。

Equals メソッドに関するその他の必須動作については、GetHashCode メソッドのトピックを参照してください。

Equals の実装が例外がスローすることはありません。

オブジェクトによっては、参照が等価なのではなく、値が等価であることを Equals でテストする必要があります。このような Equals の実装では、この 2 つのオブジェクトの "値" が同一である場合、インスタンスが異なる場合でも true が返されます。型のインプリメンタが、オブジェクトの "値" を構成するデータを決定します。通常、これはオブジェクトのインスタンス変数に格納されているデータの一部または全体です。たとえば、String の値は文字列の文字に基づいています。String クラスの Equals メソッドは、同じ文字が同じ順序で格納されている 2 つの文字列インスタンスに対し、true を返します。

IComparable を実装する型は、Equals をオーバーライドする必要があります。

Equals をオーバーライドする型は、GetHashCode もオーバーライドする必要があります。

使用するプログラミング言語で演算子をオーバーロードできる場合に、特定の型について等値演算子をオーバーロードするには、その型で Equals メソッドをオーバーライドする必要があります。このような Equals メソッドの実装では、等値演算子を使用した場合と同じ結果を返す必要があります。Equals を使用するクラス ライブラリ コードが、アプリケーション コードにより等値演算子が使用される方法と矛盾しない方法で動作するように実装するためのガイドラインを次に示します。

次のガイドラインは、値型の実装のためのものです。

  • ValueType での Equals の既定の実装よりも高いパフォーマンスを引き出すには、Equals のオーバーライドを考慮してください。

  • プログラミング言語で演算子をオーバーロードできる場合に、Equals をオーバーライドするには、値型の等値演算子をオーバーロードする必要があります。

参照型の実装のためのガイドラインを次に示します。

  • 参照型のセマンティクスが、その型がなんらかの値を表しているという事実に基づいている場合には、この参照型の Equals のオーバーライドを検討してください。

  • ほとんどの参照型では、Equals をオーバーライドする場合でも、等値演算子はオーバーロードしないでください。ただし、複素数型のような、値のセマンティクスを持つ参照型を実装する場合には、等値演算子をオーバーライドする必要があります。

現在のインスタンスと他のオブジェクトを比較するコード例を次に示します。


using System;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      Object Obj1 = new Object();
      Object Obj2 = new Object();
      outputBlock.Text += Obj1.Equals(Obj2) + "\n"; //===> false
      Obj2 = Obj1;
      outputBlock.Text += Obj1.Equals(Obj2) + "\n"; //===> true
   }
}


Equals メソッドをオーバーライドして値が等価であることを実現する Point クラスと、Point から派生した Point3D クラスの例を次に示します。Equals による Point のオーバーライドが、値が等価であることを導入するための継承チェインで最初に発生するため、基本クラスの Equals メソッド (Object から継承され、参照が等価かどうかをチェックするメソッド) は呼び出されません。ただし、Point は、値を等価にする方法で Equals を実装しているため、Point3D.EqualsPoint.Equals を呼び出します。


using System;

class Point : Object
{
   protected int x, y;

   public Point()
   {
      this.x = 0;
      this.y = 0;
   }

   public Point(int X, int Y)
   {
      this.x = X;
      this.y = Y;
   }

   public override bool Equals(Object obj)
   {
      //Check for null and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) return false;
      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }

   public override int GetHashCode()
   {
      return x ^ y;
   }
}


class Point3D : Point
{
   int z;

   public Point3D(int X, int Y, int Z)
   {
      this.x = X;
      this.y = Y;
      this.z = Z;
   }

   public override bool Equals(Object obj)
   {
      return base.Equals(obj) && z == ((Point3D)obj).z;
   }

   public override int GetHashCode()
   {
      return base.GetHashCode() ^ z;
   }
}

class Example
{

   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      Point point2D = new Point(5, 5);
      Point3D point3Da = new Point3D(5, 5, 2);
      Point3D point3Db = new Point3D(5, 5, 2);

      if (!point2D.Equals(point3Da))
      {
         outputBlock.Text += "point2D does not equal point3Da." + "\n";
      }
      if (!point3Db.Equals(point2D))
      {
         outputBlock.Text += String.Format("Likewise, point3Db does not equal point2D.") + "\n";
      }
      if (point3Da.Equals(point3Db))
      {
         outputBlock.Text += String.Format("However, point3Da equals point3Db.") + "\n";
      }

   }
}
// ----------------------------------
// Output should be:
// 
// point2D does not equal point3Da.
// Likewise, point3Db does not equal point2D.
// However, point3Da equals point3Db.


Point.Equals メソッドは、obj 引数が null ではないことと、このオブジェクトと同じ型のインスタンスを参照していることを確認します。いずれかの確認が失敗すると、このメソッドは false を返します。

Equals メソッドは、GetType を使用して、2 つのオブジェクトのランタイム型が同一かどうかを判断します。typeof は静的な型を返すため、使用されない点に注意してください。メソッドが形式 obj is Point のチェックを使用する場合、objPoint の派生クラスのインスタンスであれば、obj と現在のインスタンスのランタイム型が同一でなくても、true が返されます。2 つのオブジェクトの型が同一であることが検証されると、このメソッドは objPoint 型にキャストし、2 つのオブジェクトのインスタンス変数を比較した結果を返します。

Point3D.Equals では、継承した Equals メソッドが最初に呼び出されます。継承した Equals メソッドは、objnull ではないこと、obj がこのオブジェクトと同じクラスのインスタンスであること、および継承されたインスタンス変数が一致することを確認します。継承された Equalstrue を返す場合だけ、このメソッドは派生クラスに導入されているインスタンス変数を比較します。特に、objPoint3D 型であるか、または Point3D の派生クラスであることが確認されていない場合は、Point3D へのキャストは実行されません。

前述の例では、等値演算子を使用して各インスタンス変数が比較されています。場合によっては、次の例に示すように、Equals メソッドを使用し、Equals 実装でインスタンス変数を比較する方が適切です。


using System;

class Rectangle
{
   Point a, b;

   public Rectangle(int upLeftX, int upLeftY, int downRightX, int downRightY)
   {
      this.a = new Point(upLeftX, upLeftY);
      this.b = new Point(downRightX, downRightY);
   }

   public override bool Equals(Object obj)
   {
      // Performs an equality check on two rectangles (Point object pairs).
      if (obj == null || GetType() != obj.GetType()) return false;
      Rectangle r = (Rectangle)obj;
      //Uses Equals to compare variables.
      return a.Equals(r.a) && b.Equals(r.b);
   }

   public override int GetHashCode()
   {
      return a.GetHashCode() ^ b.GetHashCode();
   }
}

// Class Point added for clean compile
class Point
{
   private int x;
   private int y;

   public Point(int X, int Y)
   {
      this.x = X;
      this.y = Y;
   }

   public override bool Equals(Object obj)
   {
      // Performs an equality check on two points (integer pairs).
      if (obj == null || GetType() != obj.GetType()) return false;
      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }

   public override int GetHashCode()
   {
      return x.GetHashCode() ^ y.GetHashCode();
   }

}

class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {

      Rectangle r1 = new Rectangle(0, 0, 100, 200);
      Rectangle r2 = new Rectangle(0, 0, 100, 200);
      Rectangle r3 = new Rectangle(0, 0, 150, 200);

      if (r1.Equals(r2))
      {
         outputBlock.Text += "Rectangle r1 equals rectangle r2!" + "\n";
      }
      if (!r2.Equals(r3))
      {
         outputBlock.Text += "But rectangle r2 does not equal rectangle r3." + "\n";
      }
   }
}
// ------------------------------
// Output should be:
// Rectangle r1 equals rectangle r2!
// But rectangle r2 does not equal rectangle r3.


C# や Visual Basic などの一部の言語では、演算子のオーバーロードがサポートされています。等値演算子をオーバーロードする型は、Equals メソッドもオーバーライドして、同様の機能を提供する必要があります。通常は、次の例で示すように、オーバーロードされた等値演算子に置き換えて Equals メソッドを記述します。


using System;

public struct Complex
{
   public double re, im;

   public override bool Equals(Object obj)
   {
      return obj is Complex && this == (Complex)obj;
   }

   public override int GetHashCode()
   {
      return re.GetHashCode() ^ im.GetHashCode();
   }

   public static bool operator ==(Complex x, Complex y)
   {
      return x.re == y.re && x.im == y.im;
   }

   public static bool operator !=(Complex x, Complex y)
   {
      return !(x == y);
   }
}

class Example
{

   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      Complex cmplx1, cmplx2;

      cmplx1.re = 4.0;
      cmplx1.im = 1.0;

      cmplx2.re = 2.0;
      cmplx2.im = 1.0;

      if (cmplx1 != cmplx2)
         Console.WriteLine("The two objects are not equal.");
      if (! cmplx1.Equals(cmplx2))
         Console.WriteLine("The two objects are not equal.");

      cmplx2.re = 4.0;

      if (cmplx1 == cmplx2) 
         Console.WriteLine("The two objects are now equal!");
      if (cmplx1.Equals(cmplx2)) 
         Console.WriteLine("The two objects are now equal!");
   }
}
// The example displays the following output:
//       The two objects are not equal.
//       The two objects are not equal.
//       The two objects are now equal!
//       The two objects are now equal!


Complex は値型であるため、他のクラスから派生させることはできません。したがって、Equals メソッドが各オブジェクトの GetType の結果を比較する必要はありません。このメソッドは、is 演算子を使用して obj パラメーターの型を確認できます。

Windows Phone OS

サポート: 8.0, 7.1, 7.0

表示:
© 2014 Microsoft