먼저 다음 코드를 살펴보세요.
int tempi = 1; object o = tempi; double tempd = (double) o;
컴파일 시에는 통과할 수 있지만 실행 시 다음 오류가 보고됩니다.
System.InvalidCastException: 지정된 변환이 잘못되었습니다.
객체를 unboxing할 때 캐스트 결과가 원래 unboxed 유형이어야 하기 때문입니다. double 유형으로 변환하려면 먼저 int 유형으로 변환해야 합니다. 올바른 형식은 다음과 같습니다.
int tempi = 32; object o = tempi; double tempd = (double)(int) o;
.NET 프레임워크에서 박싱은 일반적으로 다음 세 단계로 구성됩니다.
1. 관리되는 힙에서 새로 생성된 참조 유형 개체에 메모리를 할당합니다. 할당된 메모리 크기는 박싱된 값 유형 인스턴스 자체의 크기에 새로 생성된 참조 유형에 대해 추가된 메서드 테이블 포인터 및 SyncBlockIndex를 더한 것입니다.
2. 인스턴스 값 유형의 필드를 관리되는 힙에 새로 할당된 개체의 메모리에 복사합니다.
3. 관리되는 힙에 새로 할당된 객체의 주소를 반환합니다. 이런 방식으로 값 유형 인스턴스도 참조 유형 객체가 됩니다.
언박싱 과정은 다음과 같습니다.
1. 언박싱할 개체가 null인 경우 NullReferenceException이 발생합니다.
2. 참조가 가리키는 개체가 예상 값 유형의 boxed 개체가 아닌 경우 unboxing이 실패하고 InvalidCastException이 발생합니다(이 문서의 시작 부분 참조).
3. 박스형 객체에 포함된 값 유형 부분에 대한 포인터가 반환됩니다. 이 포인터가 가리키는 값 유형은 참조 유형 개체가 일반적으로 갖는 추가 멤버(예: 메서드 테이블 포인터 및 SyncBlockIndex)에 대해 아무것도 모릅니다. 실제로 포인터는 이미 박싱된 개체(Microsoft.NET Framework 프로그래밍 a2c52a2a7d106cdf965ecfefd64f8924)의 박싱되지 않은 부분을 가리킵니다.
3번 항목의 경우 위의 예를 사용하면 이해를 도울 수 있습니다. 먼저 메모리에서 4바이트를 차지하는 값 유형 변수 tempi를 정의합니다. 박싱 후에는 참조 개체가 되고 메서드 테이블 포인터와 SyncBlockIndex를 추가합니다. 참조 유형의 경우 해당 값, 메소드 테이블 포인터 및 SyncBlockIndex를 가져오려면 "참조 유형"의 주소만 전달하면 됩니다. unboxing할 때 전달되는 것은 해당 "값"(unboxed 부분)의 주소입니다. 즉, 4바이트 읽기만 허용하는 "int(Int32)" 유형의 주소(참조)입니다. double 유형은 8바이트이므로 암시적 변환 시 오류가 보고됩니다. 이를 double 유형으로 변환하기 전에 int 유형으로 변환해야 합니다.
.NET에서 박싱 및 언박싱 구현 과정과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!