업데이트: 2010년 10월
네임스페이스: System어셈블리: mscorlib(mscorlib.dll)
Public Overridable Function Equals ( _ obj As Object _ ) As Boolean
public virtual bool Equals( Object obj )
public: virtual bool Equals( Object^ obj )
abstract Equals : obj:Object -> bool override Equals : obj:Object -> bool
매개 변수
- obj
- 형식: System.Object
현재 개체와 비교할 개체입니다.
Equals 의 기본 구현에서는 참조 형식에 대한 참조 일치와 값 형식에 대한 비트 일치를 지원합니다. 참조 일치는 비교되는 개체 참조가 동일한 개체를 참조함을 의미합니다. 비트 일치는 비교되는 개체에 동일한 이진 표현이 있음을 의미합니다.
파생 형식에서 Equals 메서드를 재정의하여 값 일치를 구현할 수도 있습니다. 값 일치는 이진 표현이 다른 경우에도 비교되는 개체에 동일한 값이 있음을 의미합니다. 예를 들어 숫자 1.10과 1.1000을 나타내는 두 개의 Decimal 개체가 있다고 가정합니다. 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와 y가 모두 NaN이면 x.Equals(y)는 true를 반환합니다.
-
(x.Equals(y) && y.Equals(z))에서 true를 반환하는 경우에만 x.Equals(z)에서 true를 반환합니다.
-
x와 y에서 참조하는 개체를 수정하지 않으면 x.Equals(y)로의 연속적인 호출은 동일한 값을 반환합니다.
-
x.Equals(null)는 false를 반환합니다.
Equals 메서드와 관련된 추가 동작은 GetHashCode를 참조하십시오.
Equals 의 구현은 예외를 throw할 수 없습니다.
ReferenceEquals 메서드를 호출하여 참조 같음에 대해 현재 개체를 다른 개체와 비교할 수 있습니다. Visual Basic에서는 is 키워드(예: If Me Is otherObject Then …)도 사용할 수 있습니다.
일부 개체의 경우에는 Equals를 사용하여 참조 일치 여부 대신 값 일치 여부를 확인하는 것이 좋습니다. 이러한 Equals를 구현하면 두 개체의 인스턴스는 달라도 "값"이 동일하면 true가 반환됩니다. 개체의 "값"을 구성하는 내용은 식의 구현자에 의해 결정되지만 일반적으로 개체의 인스턴스 변수에 저장된 일부 또는 모든 데이터로 구성됩니다. 예를 들어 String의 값은 해당 문자열의 문자를 기준으로 하기 때문에 String 클래스의 Equals 메서드는 동일한 문자가 동일한 순서로 들어 있는 두 문자열 인스턴스에 대해 true를 반환합니다.
IComparable 을 구현하는 형식은 Equals를 재정의해야 합니다.
Equals 를 재정의하는 형식은 GetHashCode도 재정의해야 합니다. 그렇지 않으면 Hashtable이 제대로 작동하지 않을 수 있습니다.
사용하는 프로그래밍 언어에서 연산자 오버로드를 사용할 수 있는 경우, 특정 형식에 대한 일치 연산자를 오버로드하려면 해당 형식은 Equals 메서드를 재정의해야 합니다. 이러한 Equals 메서드의 구현은 일치 연산자와 동일한 결과를 반환해야 합니다. 이 지침을 따르면 응용 프로그램 코드에서 일치 연산자를 사용하는 것과 동일한 방식으로 클래스 라이브러리에서 Equals(ArrayList나 Hashtable) 메서드를 사용할 수 있습니다.
다음은 값 형식을 구현하기 위한 지침입니다.
-
ValueType 에 대해 Equals를 재정의하면 기본 Equals 구현을 사용할 때보다 성능을 향상시킬 수 있습니다.
-
연산자 오버로드를 지원하는 언어에서 Equals 메서드를 재정의하면 값 형식에 대해 일치 연산자도 오버로드해야 합니다.
다음은 참조 형식을 구현하기 위한 지침입니다.
다음 코드 예제에서는 현재 인스턴스와 다른 개체를 비교합니다.
Imports System Imports System.IO Class Program Public Shared Sub Main(ByVal args As String()) Dim Obj1 As New Object() Dim Obj2 As New Object() Console.WriteLine(Obj1.Equals(Obj2)) Obj2 = Obj1 Console.WriteLine(Obj1.Equals(Obj2)) End Sub End Class 'This example produces the following output: 'False 'True
using System; class Program { static void Main(string[] args) { Object Obj1 = new Object(); Object Obj2 = new Object(); Console.WriteLine(Obj1.Equals(Obj2)); Obj2 = Obj1; Console.WriteLine(Obj1.Equals(Obj2)); } } /* This example produces the following output: False True */
using namespace System; void main() { Object^ Obj1 = gcnew Object; Object^ Obj2 = gcnew Object; Console::WriteLine(Obj1->Equals(Obj2)); Obj2 = Obj1; Console::WriteLine(Obj1->Equals(Obj2)); }; /* This example produces the following output: False True */
다음 예제에서는 값 일치, 그리고 Point에서 파생된 Point3D 클래스를 얻을 수 있도록 Equals 메서드를 재정의하는 Point 클래스를 보여 줍니다. Point 클래스에서 Equals 메서드를 재정의하는 것은 상속 체인에서 값 일치를 얻는 첫 번째 단계이기 때문에 기본 클래스(Object에서 상속되어 참조 일치를 확인하는 클래스)의 Equals 메서드는 호출되지 않습니다. 그러나 Point는 값 일치를 제공하도록 Equals를 구현하기 때문에 Point3D.Equals는 Point.Equals를 호출합니다.
Imports System Class Point Inherits Object Protected x, y As Integer Public Sub New() Me.x = 0 Me.y = 0 End Sub 'New Public Sub New(ByVal X As Integer, ByVal Y As Integer) Me.x = X Me.y = Y End Sub 'New Public Overrides Function Equals(ByVal obj As Object) As Boolean 'Check for null and compare run-time types. If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then Return False End If Dim p As Point = CType(obj, Point) Return x = p.x AndAlso y = p.y End Function 'Equals Public Overrides Function GetHashCode() As Integer Return x ^ y End Function 'GetHashCode End Class 'Point Class Point3D Inherits Point Private z As Integer Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Z As Integer) Me.x = X Me.y = Y Me.z = Z End Sub 'New Public Overrides Function Equals(ByVal obj As Object) As Boolean Return MyBase.Equals(obj) AndAlso z = CType(obj, Point3D).z End Function 'Equals Public Overrides Function GetHashCode() As Integer Return MyBase.GetHashCode() ^ z End Function 'GetHashCode End Class 'Point3D Class [MyClass] Public Shared Sub Main() Dim point2D As New Point(5, 5) Dim point3Da As New Point3D(5, 5, 2) Dim point3Db As New Point3D(5, 5, 2) If Not point2D.Equals(point3Da) Then Console.WriteLine("point2D does not equal point3Da.") End If If Not point3Db.Equals(point2D) Then Console.WriteLine("Likewise, point3Db does not equal point2D.") End If If point3Da.Equals(point3Db) Then Console.WriteLine("However, point3Da equals point3Db.") End If End Sub 'Main End Class '[MyClass] ' ---------------------------------- ' Output should be: ' ' point2D does not equal point3Da. ' Likewise, point3Db does not equal point2D. ' However, point3Da equals point3Db.
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 MyClass { public static void Main() { Point point2D = new Point(5, 5); Point3D point3Da = new Point3D(5, 5, 2); Point3D point3Db = new Point3D(5, 5, 2); if (!point2D.Equals(point3Da)) { Console.WriteLine("point2D does not equal point3Da."); } if (!point3Db.Equals(point2D)) { Console.WriteLine("Likewise, point3Db does not equal point2D."); } if (point3Da.Equals(point3Db)) { Console.WriteLine("However, point3Da equals point3Db."); } } } // ---------------------------------- // Output should be: // // point2D does not equal point3Da. // Likewise, point3Db does not equal point2D. // However, point3Da equals point3Db.
using namespace System; ref class Point: public Object { protected: int x; int y; public: Point() { this->x = 0; this->y = 0; } Point( int X, int Y ) { this->x = X; this->y = Y; } virtual bool Equals( Object^ obj ) override { //Check for null and compare run-time types. if ( obj == nullptr || GetType() != obj->GetType() ) return false; Point ^ p = dynamic_cast<Point^>(obj); return (x == p->x) && (y == p->y); } virtual int GetHashCode() override { return x ^ y; } }; ref class Point3D: public Point { private: int z; public: Point3D( int X, int Y, int Z ) { this->x = X; this->y = Y; this->z = Z; } virtual bool Equals( Object^ obj ) override { return Point::Equals( obj ) && z == (dynamic_cast<Point3D^>(obj))->z; } virtual int GetHashCode() override { return Point::GetHashCode() ^ z; } };
Point.Equals 메서드는 obj 인수가 null은 아닌지, 그리고 이 개체와 동일한 형식의 인스턴스를 참조하는지 확인합니다. 이를 확인할 수 없으면 메서드는 false를 반환합니다.
Equals 메서드는 GetType을 사용하여 두 개체의 런타임 형식이 동일한지 확인합니다. typeof는 정적 형식을 반환하기 때문에 여기서는 사용되지 않습니다. 메서드에 obj is Point 폼의 검사 구문이 사용된 경우, 이 구문은 obj와 현재 인스턴스의 런타임 형식이 다르더라도 obj가 Point에서 파생된 클래스의 인스턴스인 경우에는 true를 반환합니다. 두 개체의 형식이 동일하다는 것이 확인되면 메서드는 obj를 Point 형식으로 변환한 후 두 개체의 인스턴스 변수를 비교한 결과를 반환합니다.
Point3D.Equals 에서는 상속된 Equals 메서드가 가장 먼저 호출되며, 상속된 Equals 메서드는 obj가 null인지 여부, obj가 해당 개체와 동일한 클래스의 인스턴스인지 여부, 그리고 상속된 인스턴스 변수가 일치하는지 여부를 확인합니다. 메서드는 상속된 Equals 메서드에서 true를 반환하는 경우에만 파생 클래스의 인스턴스 변수를 비교합니다. Point3D로의 변환은 obj가 Point3D 형식 또는 Point3D의 파생 클래스라는 것이 확인된 경우에만 수행됩니다.
이전 예제에서는 operator ==(일치 연산자)를 사용하여 각 인스턴스 변수를 비교했습니다. 그러나 경우에 따라서는 Equals 메서드를 사용하여 Equals 구현의 인스턴스 변수를 비교하는 것이 좋습니다. 다음 코드 예제를 참조하십시오.
Imports System Class Rectangle Private a, b As Point Public Sub New(ByVal upLeftX As Integer, ByVal upLeftY As Integer, _ ByVal downRightX As Integer, ByVal downRightY As Integer) Me.a = New Point(upLeftX, upLeftY) Me.b = New Point(downRightX, downRightY) End Sub 'New Public Overrides Function Equals(ByVal obj As [Object]) As Boolean ' Performs an equality check on two rectangles (Point object pairs). If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then Return False End If Dim r As Rectangle = CType(obj, Rectangle) 'Uses Equals to compare variables. Return a.Equals(r.a) AndAlso b.Equals(r.b) End Function 'Equals Public Overrides Function GetHashCode() As Integer Return a.GetHashCode() ^ b.GetHashCode() End Function 'GetHashCode End Class 'Rectangle ' Class Point added for clean compile Class Point Private x As Integer Private y As Integer Public Sub New(ByVal X As Integer, ByVal Y As Integer) Me.x = X Me.y = Y End Sub 'New Public Overrides Function Equals(ByVal obj As [Object]) As Boolean ' Performs an equality check on two points (integer pairs). If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then Return False End If Dim p As Point = CType(obj, Point) Return x = p.x AndAlso y = p.y End Function 'Equals Public Overrides Function GetHashCode() As Integer Return x.GetHashCode() ^ y.GetHashCode() End Function 'GetHashCode End Class 'Point Class [MyClass] Public Shared Sub Main() Dim r1 As New Rectangle(0, 0, 100, 200) Dim r2 As New Rectangle(0, 0, 100, 200) Dim r3 As New Rectangle(0, 0, 150, 200) If r1.Equals(r2) Then Console.WriteLine("Rectangle r1 equals rectangle r2!") End If If Not r2.Equals(r3) Then Console.WriteLine("But rectangle r2 does not equal rectangle r3.") End If End Sub 'Main End Class '[MyClass] ' ------------------------------ ' Output should be: ' Rectangle r1 equals rectangle r2! ' But rectangle r2 does not equal rectangle r3.
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 MyClass { 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); if (r1.Equals(r2)) { Console.WriteLine("Rectangle r1 equals rectangle r2!"); } if (!r2.Equals(r3)) { Console.WriteLine("But rectangle r2 does not equal rectangle r3."); } } } // ------------------------------ // Output should be: // Rectangle r1 equals rectangle r2! // But rectangle r2 does not equal rectangle r3.
ref class Rectangle { private: Point^ a; Point^ b; public: Rectangle( int upLeftX, int upLeftY, int downRightX, int downRightY ) { this->a = gcnew Point( upLeftX,upLeftY ); this->b = gcnew Point( downRightX,downRightY ); } virtual bool Equals( Object^ obj ) override { // Performs an equality check on two rectangles (Point object pairs). if ( obj == nullptr || GetType() != obj->GetType() ) return false; Rectangle^ r = dynamic_cast<Rectangle^>(obj); //Uses Equals to compare variables. return a->Equals( r->a ) && b->Equals( r->b ); } virtual int GetHashCode() override { return a->GetHashCode() ^ b->GetHashCode(); } };
C# 및 Visual Basic 등의 일부 언어에서는 연산자 오버로드가 지원됩니다. 한 형식에서 같음 연산자를 오버로드하면 해당 형식은 동인한 기능을 제공할 수 있도록 Equals 메서드도 재정의해야 합니다. 대개는 다음 예제에서와 같이 오버로드된 같음 연산자에 따라 Equals 메서드를 작성하면 됩니다.
Public Structure Complex Public re, im As Double Public Overrides Function Equals(ByVal obj As [Object]) As Boolean Return TypeOf obj Is Complex AndAlso Me = CType(obj, Complex) End Function Public Overrides Function GetHashCode() As Integer Return re.GetHashCode() ^ im.GetHashCode() End Function Public Shared Operator = (x As Complex, y As Complex) As Boolean Return x.re = y.re AndAlso x.im = y.im End Operator Public Shared Operator <> (x As Complex, y As Complex) As Boolean Return Not (x = y) End Operator End Structure Class Example Public Shared Sub Main() Dim cmplx1, cmplx2 As Complex cmplx1.re = 4.0 cmplx1.im = 1.0 cmplx2.re = 2.0 cmplx2.im = 1.0 If cmplx1 <> cmplx2 Then Console.WriteLine("The two objects are not equal.") End If If Not cmplx1.Equals(cmplx2) Then Console.WriteLine("The two objects are not equal.") End If cmplx2.re = 4.0 If cmplx1.Equals(cmplx2) Then Console.WriteLine("The two objects are now equal!") End If If cmplx1 = cmplx2 Then Console.WriteLine("The two objects are now equal!") End If End Sub End Class ' 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!
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 MyClass { public static void Main() { 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!
using namespace System; public value struct Complex { public: double re; double im; virtual bool Equals( Object^ obj ) override { return (dynamic_cast<Complex^>(obj) != nullptr) && (*this == *dynamic_cast<Complex^>(obj)); } virtual int GetHashCode() override { return re.GetHashCode() ^ im.GetHashCode(); } static bool operator==( Complex x, Complex y ) { return x.re == y.re && x.im == y.im; } static bool operator!=( Complex x, Complex y ) { return !(x == y); } }; int main() { Complex cmplx1; Complex 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 는 C# 구조체(값 형식)이기 때문에 아무것도 파생시킬 수 없습니다. 따라서 Equals 메서드는 각 개체의 GetType 결과를 비교할 필요없이 is 연산자를 대신 사용하여 obj 매개 변수의 형식을 확인할 수 있습니다.
.NET Framework
4, 3.5, 3.0, 2.0, 1.1, 1.0에서 지원.NET Framework Client Profile
4, 3.5 SP1에서 지원에서 지원
Windows 7, Windows Vista SP1 이상, Windows XP SP3, Windows XP SP2 x64 버전, Windows Server 2008(Server Core는 지원되지 않음), Windows Server 2008 R2(Server Core는 SP1 이상에서 지원됨), Windows Server 2003 SP2
.NET Framework에서 모든 플랫폼의 전체 버전을 지원하지는 않습니다. 지원되는 버전의 목록을 보려면 .NET Framework 시스템 요구 사항을 참조하십시오.
참조
|
날짜 |
변경 내용 |
이유 |
|---|---|---|
|
2010년 10월 |
마지막 예제를 수정했습니다. |
고객 의견 |