本文為機器翻譯文章。如需檢視英文版,請選取 [原文] 核取方塊。您也可以將滑鼠指標移到文字上,即可在快顯視窗顯示英文原文。
譯文
原文

Object.Equals 方法 (Object)

 

判斷指定的物件是否等於目前的物件。

命名空間:   System
組件:  mscorlib (於 mscorlib.dll)

public virtual bool Equals(
	object obj
)

參數

obj
Type: System.Object

要與目前物件比較的物件。

傳回值

Type: System.Boolean

如果指定的物件等於目前的物件,則為 true,否則為 false

比較目前的執行個體之間的類型和obj參數,取決於目前的執行個體是參考類型或實值類型。

  • 如果目前的執行個體是參考類型,Equals(Object)方法測試參考是否相等,而呼叫Equals(Object)方法相當於呼叫ReferenceEquals方法。 參考相等,表示要比較的物件變數會參照相同的物件。 下列範例說明這類比較的結果。 它會定義Person類別,這是參考類型,並呼叫Person類別建構函式來產生兩個新Person物件person1aperson2,必須有相同的值。 它也會將指派person1a給另一個物件變數, person1b 做為範例所示,從輸出person1aperson1b相等,因為其參考相同的物件。 不過,person1aperson2不相等,雖然它們有相同的值。

    using System;
    
    // Define a reference type that does not override Equals.
    public class Person
    {
       private string personName;
    
       public Person(string name)
       {
          this.personName = name;
       }
    
       public override string ToString()
       {
          return this.personName;
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person person1a = new Person("John");
          Person person1b = person1a;
          Person person2 = new Person(person1a.ToString());
    
          Console.WriteLine("Calling Equals:"); 
          Console.WriteLine("person1a and person1b: {0}", person1a.Equals(person1b));               
          Console.WriteLine("person1a and person2: {0}", person1a.Equals(person2));  
    
          Console.WriteLine("\nCasting to an Object and calling Equals:");
          Console.WriteLine("person1a and person1b: {0}", ((object) person1a).Equals((object) person1b));
          Console.WriteLine("person1a and person2: {0}", ((object) person1a).Equals((object) person2)); 
       }
    }
    // The example displays the following output:
    //       person1a and person1b: True
    //       person1a and person2: False
    //       
    //       Casting to an Object and calling Equals:
    //       person1a and person1b: True
    //       person1a and person2: False
    
  • 如果目前的執行個體是實值類型,Equals(Object)方法測試值是否相等。 值相等的意義如下︰

    • 兩個物件都屬於相同的型別。 如下列範例所示,Byte有 12 個值的物件不等於Int32有其值為 12,因為兩個物件具有不同的執行階段類型的物件。

      using System;
      
      public class Example
      {
         public static void Main()
         {
            byte value1 = 12;
            int value2 = 12;
      
            object object1 = value1;
            object object2 = value2;
      
            Console.WriteLine("{0} ({1}) = {2} ({3}): {4}",
                              object1, object1.GetType().Name,
                              object2, object2.GetType().Name,
                              object1.Equals(object2));
         }
      }
      // The example displays the following output:
      //        12 (Byte) = 12 (Int32): False
      
    • 兩個物件的公用和私用欄位的值相等。 下列範例會測試的值相等。 它會定義Person結構,也就是實值類型,並呼叫Person類別建構函式來產生兩個新Person物件person1person2,必須有相同的值。 範例輸出所示,不過兩個物件變數參考不同的物件,person1person2相等,因為它們具有相同的值與私人personName欄位。

      using System;
      
      // Define a value type that does not override Equals.
      public struct Person
      {
         private string personName;
      
         public Person(string name)
         {
            this.personName = name;
         }
      
         public override string ToString()
         {
            return this.personName;
         }
      }
      
      public struct Example
      {
         public static void Main()
         {
            Person person1 = new Person("John");
            Person person2 = new Person("John");
      
            Console.WriteLine("Calling Equals:"); 
            Console.WriteLine(person1.Equals(person2)); 
      
            Console.WriteLine("\nCasting to an Object and calling Equals:");
            Console.WriteLine(((object) person1).Equals((object) person2));  
         }
      }
      // The example displays the following output:
      //       Calling Equals:
      //       True
      //       
      //       Casting to an Object and calling Equals:
      //       True
      

因為Object類別是.NET Framework 中中的所有類型的基底類別Object.Equals(Object)方法提供對於所有其他類型的預設相等比較。 不過,型別通常覆寫Equals方法,以實作值是否相等。 如需詳細資訊,請參閱 < 附註的呼叫端和注意事項繼承者區段。

當您呼叫Equals(Object)中之類別的方法多載Windows 執行階段,它提供的預設行為不覆寫的類別Equals(Object) 這是 .NET Framework 針對 Windows 執行階段 提供的部分支援 (參閱 適用於 Windows 市集應用程式和 Windows 執行階段的 .NET Framework 支援)。 中的類別Windows 執行階段不繼承Object,且不要只實作目前Equals(Object)方法。 不過,它們便會顯示有ToStringEquals(Object),和GetHashCode時您用於您的 C# 或 Visual Basic 程式碼,以及.NET Framework 提供的預設行為,這些方法的方法。

System_CAPS_note注意

Windows 執行階段以 C# 或 Visual Basic 撰寫的類別可以覆寫Equals(Object)方法多載。

經常衍生的類別覆寫Object.Equals(Object)方法,以實作值是否相等。 此外,型別也經常會提供額外的強型別多載來Equals方法,通常是藉由實作IEquatable<T>介面。 當您呼叫Equals方法來測試是否相等,您應該知道是否會覆寫目前的執行個體Object.Equals並了解如何在特定呼叫Equals方法已解決。 否則,您可能執行的測試相等,不同於您想要的結果,而且方法可能會傳回非預期的值。

下列範例提供一個實例。 它會具現化三個StringBuilder物件與相同的字串,並接著四個呼叫Equals方法。 第一個方法呼叫傳回true,和剩餘的三個傳回false

using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      StringBuilder sb1 = new StringBuilder("building a string...");
      StringBuilder sb2 = new StringBuilder("building a string...");

      Console.WriteLine("sb1.Equals(sb2): {0}", sb1.Equals(sb2));
      Console.WriteLine("((Object) sb1).Equals(sb2): {0}", 
                        ((Object) sb1).Equals(sb2));
      Console.WriteLine("Object.Equals(sb1, sb2): {0}",
                        Object.Equals(sb1, sb2));      

      Object sb3 = new StringBuilder("building a string...");
      Console.WriteLine("\nsb3.Equals(sb2): {0}", sb3.Equals(sb2));                              
   }
}
// The example displays the following output:
//       sb1.Equals(sb2): True
//       ((Object) sb1).Equals(sb2): False
//       Object.Equals(sb1, sb2): False
//
//       sb3.Equals(sb2): False

在第一個案例中,強型別StringBuilder.Equals(StringBuilder)方法多載,測試值是否相等,會呼叫。 因為字串指派給這兩個StringBuilder物件是否相等,則方法會傳回true 不過,StringBuilder不會覆寫Object.Equals(Object) 因為這個緣故時,StringBuilder物件轉換成Object,當StringBuilder執行個體指派給變數的型別Object,和當Object.Equals(Object, Object)方法會傳遞兩個StringBuilder物件,則預設Object.Equals(Object)方法呼叫。 因為StringBuilder是參考類型,這相當於傳遞兩個StringBuilder物件加入至ReferenceEquals方法。 雖然這三個StringBuilder物件包含完全相同的字串,它們會參考至三個相異的物件。 如此一來,這些三個方法呼叫傳回false

您可以藉由呼叫比較目前物件與另一個物件的參考相等性ReferenceEquals方法。 在 Visual Basic 中,您也可以使用is關鍵字 (例如, If Me Is otherObject Then ...)。

當您定義自己的型別時,該類型繼承所定義的功能Equals其基底型別的方法。 下表列出的預設實作Equals方法在.NET Framework 類型的主要類別。

型別分類

所定義的相等

註解

直接衍生自類別Object

Object.Equals(Object)

參考相等。相當於呼叫Object.ReferenceEquals

結構

ValueType.Equals

值相等。直接位元組的比較或欄位的欄位比較使用反映。

列舉

Enum.Equals

值必須有相同的列舉類型與相同的基礎值。

delegate

MulticastDelegate.Equals

委派必須具有相同的引動過程清單的相同類型。

interface

Object.Equals(Object)

參考相等。

對於實值類型,您應該一律覆寫Equals,因為依賴反映的等號比較測試會提供效能不佳。 您也可以覆寫的預設實作Equals參考類型的值是否相等,而不是參考相等測試,以及定義精確意義的值是否相等。 這類實作Equals傳回true如果兩個物件擁有相同的值,即使它們不是相同的執行個體。 型別實作器決定何者構成物件的值,但是它通常是部分或所有儲存的資料物件的執行個體變數中。 例如,值String物件為基礎的字元字串;String.Equals(Object)方法覆寫Object.Equals(Object)方法以傳回true任何兩個字串含有相同的順序中的相同字元的執行個體。

下列範例示範如何覆寫Object.Equals(Object)方法來測試值是否相等。 它會覆寫Equals方法Person類別。 如果Person接受等號比較、 其基底類別實作兩個Person會等於只有當參考單一物件,這些物件。 不過,在此情況下,兩個Person物件是否相等,如果它們有相同的值Person.Id屬性。

public class Person
{
   private string idNumber;
   private string personName;

   public Person(string name, string id)
   {
      this.personName = name;
      this.idNumber = id;
   }

   public override bool Equals(Object obj)
   {
      Person personObj = obj as Person; 
      if (personObj == null)
         return false;
      else
         return idNumber.Equals(personObj.idNumber);
   }

   public override int GetHashCode()
   {
      return this.idNumber.GetHashCode(); 
   }
}

public class Example
{
   public static void Main()
   {
      Person p1 = new Person("John", "63412895");
      Person p2 = new Person("Jack", "63412895");
      Console.WriteLine(p1.Equals(p2));
      Console.WriteLine(Object.Equals(p1, p2));
   }
}
// The example displays the following output:
//       True
//       True

除了覆寫Equals,您可以實作IEquatable<T>介面,以提供強型別的測試是否相等。

下列陳述式必須為 true 的所有實作Equals(Object)方法。 在清單中, xy,和z代表物件參考未null

  • x.Equals(x)傳回true,除非在涉及浮點類型的情況下。 請參閱 ISO/IEC/IEEE 60559:2011,資訊技術-微處理器系統-浮點算術。

  • x.Equals(y)傳回相同的值做為y.Equals(x)

  • x.Equals(y)傳回true如果兩個xyNaN

  • 如果(x.Equals(y) && y.Equals(z))傳回true,然後x.Equals(z)傳回true

  • 後續呼叫x.Equals(y)傳回相同的值,只要參考的物件xy不會修改。

  • x.Equals(null) 會傳回 false

實作Equals必須不會擲回例外狀況,他們應該一律會傳回的值。 例如,如果objnullEquals方法應傳回false而不是擲回ArgumentNullException

覆寫時,請遵循下列方針Equals(Object):

  • 型別都會實作IComparable必須覆寫Equals(Object)

  • 類型覆寫Equals(Object)也必須覆寫GetHashCode,否則雜湊表可能無法正常運作。

  • 您應該考慮實作IEquatable<T>介面,以支援強型別測試是否相等。IEquatable<T>.Equals實作應該傳回一致的結果Equals

  • 如果您的程式語言支援運算子多載,而且您多載等號比較運算子,針對指定的型別,您也必須覆寫Equals(Object)方法以傳回與等號比較運算子相同的結果。 這有助於確保會使用該類別程式庫程式碼Equals(例如ArrayListHashtable) 行為與等號比較運算子由應用程式程式碼的方式一致的方式。

下列指導方針適用於覆寫Equals(Object)是參考型別︰

  • 請考慮覆寫Equals如果類型的語意是基礎類型所代表的某些值為基礎。

  • 大部分的參考型別必須多載等號比較運算子,即使它們覆寫Equals 不過,如果您實作的參考類型,這是具有實值語意,例如複數類型,您必須覆寫等號比較運算子。

  • 您不應覆寫Equals可變動參考類型上。 這是因為覆寫Equals需要,您也會覆寫GetHashCode方法,如前一節中討論。 這表示可變動參考類型的執行個體的雜湊程式碼可以在其生命週期,這可能導致遺失物件雜湊表中變更。

下列指導方針適用於覆寫Equals(Object)的實值類型︰

  • 如果您要定義實值型別,其中包含一個或多個欄位的值是參考類型,您應該覆寫Equals(Object) Equals(Object)提供實作ValueType執行位元組的比較的值類型欄位所有實值類型,但它會使用反映來執行其欄位包含參考類型的實值類型欄位的欄位比較。

  • 如果您覆寫Equals和您的開發語言支援運算子多載,您必須多載等號比較運算子。

  • 您應該實作IEquatable<T>介面。 呼叫的強型別IEquatable<T>.Equals方法可以避免 boxingobj引數。

下列範例所示Point類別會覆寫Equals方法以提供實值相等和Point3D類別衍生自Point 因為Point會覆寫Object.Equals(Object)來測試值是否相等,Object.Equals(Object)不會呼叫方法。 不過,Point3D.Equals呼叫Point.Equals因為Point實作Object.Equals(Object)方式提供值是否相等。

using System;

class Point
{
   protected int x, y;

   public Point() : this(0, 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) || ! this.GetType().Equals(obj.GetType())) {
         return false;
      }
      else { 
         Point p = (Point) obj; 
         return (x == p.x) && (y == p.y);
      }   
   }

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

    public override string ToString()
    {
        return String.Format("Point({0}, {1})", x, y);
    }
}

sealed class Point3D: Point 
{
   int z;

   public Point3D(int x, int y, int z) : base(x, y) 
   {
      this.z = z; 
   }

   public override bool Equals(Object obj) 
   {
      Point3D pt3 = obj as Point3D;
      if (pt3 == null)
         return false;
      else
         return base.Equals((Point)obj) && z == pt3.z;
   }

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

   public override String ToString() 
   {
        return String.Format("Point({0}, {1}, {2})", x, y, z);
    }
}

class Example 
{
  public static void Main() 
  {
     Point point2D = new Point(5, 5);
     Point3D point3Da = new Point3D(5, 5, 2);
     Point3D point3Db = new Point3D(5, 5, 2);
     Point3D point3Dc = new Point3D(5, 5, -1);

     Console.WriteLine("{0} = {1}: {2}", 
                       point2D, point3Da, point2D.Equals(point3Da));
     Console.WriteLine("{0} = {1}: {2}", 
                       point2D, point3Db, point2D.Equals(point3Db));        
     Console.WriteLine("{0} = {1}: {2}", 
                       point3Da, point3Db, point3Da.Equals(point3Db));
     Console.WriteLine("{0} = {1}: {2}", 
                       point3Da, point3Dc, point3Da.Equals(point3Dc));
  } 
}
// The example displays the following output:
//       Point(5, 5) = Point(5, 5, 2): False
//       Point(5, 5) = Point(5, 5, 2): False
//       Point(5, 5, 2) = Point(5, 5, 2): True
//       Point(5, 5, 2) = Point(5, 5, -1): False

The Point.Equals method checks to make sure that the obj argument is not null and that it references an instance of the same type as this object. If either check fails, the method returns false.

The Point.Equals method calls the M:System.Object.GetType method to determine whether the run-time types of the two objects are identical. If the method used a check of the form obj is Point in C# or TryCast(obj, Point) in Visual Basic, the check would return true in cases where obj is an instance of a derived class of Point, even though obj and the current instance are not of the same run-time type. Having verified that both objects are of the same type, the method casts obj to type Point and returns the result of comparing the instance fields of the two objects.

In Point3D.Equals, the inherited Point.Equals method, which overrides M:System.Object.Equals(System.Object), is invoked before anything else is done. Because Point3D is a sealed class (NotInheritable in Visual Basic), a check in the form obj is Point in C# or TryCast(obj, Point) in Visual Basic is adequate to ensure that obj is a Point3D object. If it is a Point3D object, it is cast to a Point object and passed to the base class implementation of M:System.Object.Equals(System.Object). Only when the inherited Point.Equals method returns true does the method compare the z instance fields introduced in the derived class.

下列範例會定義Rectangle類別,以在內部實作做為兩個矩形Point物件。 Rectangle類別也會覆寫Object.Equals(Object)提供的值是否相等。

using System;

class Rectangle 
{
   private 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) {
      // Perform an equality check on two rectangles (Point object pairs).
      if (obj == null || GetType() != obj.GetType()) 
          return false;
      Rectangle r = (Rectangle)obj;
      return a.Equals(r.a) && b.Equals(r.b);
   }

   public override int GetHashCode() {
      return Tuple.Create(a, b).GetHashCode();
   }

    public override String ToString() 
    {
       return String.Format("Rectangle({0}, {1}, {2}, {3})",
                            a.x, a.y, b.x, b.y); 
    }
}

class Point 
{
  internal int x;
  internal 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 Tuple.Create(x, y).GetHashCode();
  }
}

class Example 
{
   public static void Main() 
   {
      Rectangle r1 = new Rectangle(0, 0, 100, 200);
      Rectangle r2 = new Rectangle(0, 0, 100, 200);
      Rectangle r3 = new Rectangle(0, 0, 150, 200);

      Console.WriteLine("{0} = {1}: {2}", r1, r2, r1.Equals(r2));
      Console.WriteLine("{0} = {1}: {2}", r1, r3, r1.Equals(r3));
      Console.WriteLine("{0} = {1}: {2}", r2, r3, r2.Equals(r3));
   }
}
// The example displays the following output:
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 100, 200): True
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False

某些語言,例如 C# 和 Visual Basic 支援運算子多載。 當類型多載等號比較運算子時,它也必須覆寫Equals(Object)方法以提供相同的功能。 這通常會透過撰寫Equals(Object)方面的多載等號比較運算子,如下列範例所示的方法。

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 Tuple.Create(re, 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);
   }

    public override String ToString()
    {
       return String.Format("({0}, {1})", re, im);
    } 
}

class MyClass 
{
  public static void Main() 
  {
    Complex cmplx1, cmplx2;

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

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

    Console.WriteLine("{0} <> {1}: {2}", cmplx1, cmplx2, cmplx1 != cmplx2);        
    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));        

    cmplx2.re = 4.0;

    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1 == cmplx2);        
    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));          
  }
}
// The example displays the following output:
//       (4, 1) <> (2, 1): True
//       (4, 1) = (2, 1): False
//       (4, 1) = (4, 1): True
//       (4, 1) = (4, 1): True

Because Complex is a value type, it cannot be derived from. Therefore, the override to M:System.Object.Equals(System.Object) method need not call M:System.Object.GetType to determine the precise run-time type of each object, but can instead use the is operator in C# or the TypeOf operator in Visual Basic to check the type of the obj parameter.

通用 Windows 平台
自 8 起供應
.NET Framework
自 1.1 起供應
可攜式類別庫
提供支援︰ 可攜式 .NET 平台
Silverlight
自 2.0 起供應
Windows Phone Silverlight
自 7.0 起供應
Windows Phone
自 8.1 起供應
回到頁首
顯示: