* 정의

 

- 박싱(Boxing)

 

박싱이란 값 타입을 object나 인터페이스 타입(해당 값 타입이 상속하고 있는 인터페이스)으로 변환하는 과정이다. CLR이 값 타입을 박싱할 때 값을 object(System.Object)에 래핑하여 힙에 저장된다.(원래 기본적으로 값 타입은 스택에 저장된다.)

 

 

- 언박싱(Unboxing)

 

언박싱이란 object로 부터 값 타입을 추출하는 과정이다.

 

 

박싱은 암묵적으로 이루어지고 언박싱은 명시적으로 수행된다.  C#에서 박싱과 언박싱을 통해 어떤 값 타입이라도 object로 다룰 수 있게 된다.

 

 

* 동작 방식

 

- 박싱과 언박싱이 발생하는 시점

 

예를 들어 값 타입 int i 와 object o 사이의 박싱 언박싱 과정은 다음과 같은 코드에서 나타난다.

 

i 가 박싱되고 o에 할당되는 과정이다.

int  i = 3;

// 박싱
object o = i;

 

o가 언박싱되고 i에 할당되는 과정이다.

object o = 3;

// 언박싱
i = (int)o;

 

 

박싱과 언박싱은 둘 다 비싼 연산이다. 박싱 연산은 힙에 할당하는 작업도 포함되어 있기 때문에 더 비싸다. 내부 동작 원리를 확인해보면 이유를 알 수 있다.

 

 

- 박싱의 원리

 

박싱은 값 타입을 가비지 컬렉터가 관리하는 힙에 할당하기 위해 사용되며, 값 타입에서 object, 인터페이스 타입(값 타입이 상속 받고 있는 인터페이스)으로의 암묵적 변환을 의미한다. 값 타입을 박싱하는 것은 object 인스턴스를 힙에 할당하고 값을 새로운 object에 복사하는 작업이다. 새롭게 힙에 할당하기 때문에 박싱된 값 타입(힙)과 값 타입 원본(스택)은 독립된 메모리 공간에 위치한다.

 

 

 

ildasm을 통해서 보면 OpCode가 box인 것을 확인할 수 있다.

 

 

- 언박싱의 원리

 

언박싱은 object나 인터페이스 타입에서 값 타입으로의 명시적 변환을 의미한다. 언박싱 연산은 다음과 같이 구성된다.

 

  • object 인스턴스를 검사하여 변환할 값 타입으로 object에 박싱되었는지 확인한다.
  • 인스턴스에서 값 타입 변수로 값을 복사한다.

 

 

 

ildasm을 통해서 보면 OpCode가 unbox인 것을 확인할 수 있다.

 

 

런타임에서 문제 없이 값 타입 언박싱이 수행되려면 언박싱할 값 타입이 이전에 해당 값 타입을 박싱하여 생성된 객체(에 대한 참조)가 언박싱 되어야 한다.

 

null을 언박싱하면 NullReferenceException, 호환불가능한 값으로 언박싱하면 InvalidCastException이 발생한다.

int i = 3;
object o = i; // 박싱
//short s = (short)o; // 언박싱과정에서 InvalidCastException 발생

object? o2 = null;
int i2 = (int)o2; // 언박싱과정에서 NullReferenceExceptino 발생
// 사실 (int) 으로 캐스팅을 시도하는 시점에서 컴파일러가 경고 메시지를 출력한다.

 

 

* 박싱 언박싱 유무 성능 비교

 

object 타입을 요소로 가지고 있는 Collection의 ArrayList와 여러 타입 인수를 통해 요소의 타입을 결정할 수 있는 Generic Collection의 List를 간단히 성능 비교해보았다.

ildasm을 통해서 보았을 때 box, unbox 명령어가 Collection 버전에서만 나타났다.

 

 

 

 

'C#' 카테고리의 다른 글

[C#] 강력한 형식 언어(Strongly Typed Language)  (0) 2022.06.28
[C#] var  (0) 2022.06.28
[C#] object  (0) 2022.06.28
[C#] string vs StringBuilder  (0) 2022.06.28
[C#] Nullable 타입  (0) 2022.06.28

+ Recent posts