IT박스

(object) 0 == (object) 0이 ((object) 0) .Equals ((object) 0)과 다른 이유는 무엇입니까?

itboxs 2020. 7. 18. 22:49
반응형

(object) 0 == (object) 0이 ((object) 0) .Equals ((object) 0)과 다른 이유는 무엇입니까?


다음 표현이 다른 이유는 무엇입니까?

[1]  (object)0 == (object)0 //false
[2]  ((object)0).Equals((object)0) // true

실제로 .NET 런타임이 box정수를 사용하고 대신 참조 비교를 시작 하기 때문에 [1]을 완전히 이해할 수 있습니다 . 그러나 왜 [2]가 다른가?


호출이 다르게 동작하는 이유는 매우 다른 메소드에 바인딩하기 때문입니다.

==사례는 정적 참조 항등 연산자에 바인딩됩니다. 2 개의 독립적 인 박스 int값이 생성되므로 동일한 참조가 아닙니다.

두 번째 경우에는 인스턴스 메소드에 바인딩합니다 Object.Equals. 이것은 필터링되는 가상 방법이며 Int32.Equals박스형 정수를 확인합니다. 두 정수 값은 모두 0이므로 동일합니다.


int 값 0(또는 다른 값 유형)을로 캐스팅 object하면 값이 상자로 표시 됩니다. 각 캐스트 object는 다른 상자 (즉, 다른 객체 인스턴스) 생성합니다. 유형 ==연산자 object는 참조 비교를 수행하므로 왼쪽과 오른쪽이 동일한 인스턴스가 아니기 때문에 false를 반환합니다.

반면에 Equals가상 메서드 인을 사용하면 실제 박스 형식의 구현을 사용합니다. 즉 Int32.Equals, 두 개체의 값이 같으므로 true를 반환합니다.


==작업자는 고정되고, 가상이 아니다. object클래스가 정의한 정확한 코드 (`오브젝트의 컴파일 시간 유형 인 객체 ')를 실행하며, 객체의 런타임 유형에 관계없이 참조 비교를 수행합니다.

Equals방법은 가상 인스턴스 방법입니다. object클래스 의 코드가 아닌 (첫 번째) 객체의 실제 런타임 유형에 정의 된 코드를 실행합니다 . 이 경우 객체는입니다 int. 따라서 해당 int유형이 Equals메소드에 대해 정의한 것과 같이 값 비교를 수행합니다 .


Equals()방법은 가상입니다.
따라서 호출 사이트가로 캐스팅 된 경우에도 항상 구체적인 구현을 호출합니다 object. 값으로 비교하기 위해 int재정의 Equals()하므로 값 비교를 얻습니다.


== 사용하다: Object.ReferenceEquals

Object.Equals 값을 비교합니다.

object.ReferenceEquals방법은 참조를 비교합니다. 객체를 할당 할 때 메모리 힙의 객체 데이터와 함께 메모리 위치를 나타내는 값이 포함 된 참조가 수신됩니다.

object.Equals방법은 객체의 내용을 비교합니다. 먼저 object.ReferenceEquals와 같이 참조가 동일한 지 확인합니다. 그런 다음 파생 된 Equals 메소드를 호출하여 동등성을 더 테스트합니다. 이것 좀 봐:

   System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b);  //returns true

C # 연산자는 토큰 ==사용하여 두 가지 다른 연산자 (정적으로 오버로드 가능한 비교 연산자 및 오버로드 할 수없는 참조 비교 연산자)를 나타냅니다. ==토큰 이 발견되면 먼저 피연산자 유형에 적용 가능한 동등성 테스트 과부하가 있는지 확인합니다. 그렇다면 해당 과부하를 호출합니다. 그렇지 않으면 유형이 참조 비교 연산자에 적용 가능한지 확인합니다. 그렇다면 해당 연산자를 사용합니다. 피연산자 유형에 적용 할 수있는 연산자가 없으면 컴파일이 실패합니다.

코드 (Object)0는 단순히 Int32to Object:를 업 캐스트하지 않습니다 . Int32모든 값 유형과 마찬가지로 실제로 두 가지 유형을 나타냅니다. 하나는 값과 저장 위치 (예 : 리터럴 0)를 설명하지만 어떤 것도 파생되지 않으며 다른 하나는 설명하지 않습니다. 힙 객체와 다음에서 파생됩니다 Object. 후자 유형 만 업 캐스트 될 수 있으므로 Object컴파일러는 해당 유형의 새 힙 객체를 작성해야합니다. 호출 할 때마다 (Object)0새 힙 객체 만들어 지므로 두 피연산자 ==는 서로 다른 객체가되며 각각은 독립적으로 Int32값 0을 캡슐화합니다 .

이 클래스 Object에는 equals 연산자에 정의 된 사용 가능한 과부하가 없습니다. 결과적으로 컴파일러는 오버로드 된 동등성 테스트 연산자를 사용할 수 없으며 참조 평등 테스트를 사용합니다. 두 피연산자는 ==서로 다른 개체를 나타내므로보고 false합니다. 두 번째 비교는 하나의 힙 객체 인스턴스가 Int32다른 것과 동일한 지 여부를 묻기 때문에 성공합니다 . 해당 인스턴스는 다른 개별 인스턴스와 동등한 의미를 알고 있으므로에 응답 할 수 있습니다 true.


두 검사가 다릅니다. 위한 첫 번째 수표 의 신원 에 대한 두번째 같음 . 일반적으로 두 개의 용어가 동일한 객체를 참조하면 동일합니다. 이것은 그들이 동등하다는 것을 의미합니다. 값이 같으면 두 항이 같습니다.

프로그래밍 아이덴티티의 관점에서 보통 참조 평등에 의해 엉망이됩니다. 두 용어에 대한 포인터가 같으면 (!), 그들이 가리키는 객체는 정확히 같은 객체입니다. 그러나 포인터가 다른 경우 포인터가 가리키는 객체의 값은 여전히 ​​동일 할 수 있습니다. C #에서는 정적 Object.ReferenceEquals멤버를 사용하여 ID를 확인할 수 있고 비 정적 Object.Equals멤버를 사용하여 동등성을 검사 할 수 있습니다 . 두 개의 정수 ( "boxing", btw라고 함)를 캐스팅하기 때문에의 연산자 ==object기본적으로 첫 번째 확인 수행합니다. 이는 기본적으로 매핑되어 Object.ReferenceEqualsID를 확인합니다. 비 정적 Equals구성원 을 명시 적으로 호출하면 동적 디스패치 결과가로 호출되어 Int32.Equals동등성을 확인합니다.

두 개념은 비슷하지만 동일하지는 않습니다. 처음에는 혼란스러워 보일 수 있지만 작은 차이가 매우 중요합니다! "Alice"와 "Bob"두 사람을 상상해보십시오. 그들은 둘 다 노란 집에 살고 있습니다. 앨리스와 밥은 집의 색깔이 다른 지역에 살고 있다는 가정을 바탕으로 서로 다른 노란 집에 살 수 있습니다. 두 가정을 비교하면 모두 노란색이기 때문에 절대적으로 동일하다는 것을 알 수 있습니다! 그러나 그들은 같은 집을 공유하지 않기 때문에 그들의 집은 동일 하지만 동일 하지는 않습니다 . 정체성은 그들이 같은 집에 살고 있음을 의미합니다 .

참고 : 일부 언어는 ===ID를 확인하기 위해 연산자를 정의하고 있습니다.

참고 URL : https://stackoverflow.com/questions/20642202/why-is-object0-object0-different-from-object0-equalsobject0

반응형