박싱이란 값 타입(Value Type) 데이터를 참조 타입(Reference Type)으로 변환하는 과정이다.
쉽게 말해, 스택(Stack)에 존재하는 값을 힙(Heap)에 복사해서, 객체(Object)처럼 사용하는 것.
예시
int num = 123; // 값 타입 (스택에 저장)
object obj = num; // 박싱 발생 (힙에 int 값을 복사, obj는 참조 타입)
이 코드를 실행하면, 다음과 같은 일이 발생한다.
num이라는 int 값(값 타입)이 있다.
object는 참조 타입이기 때문에, 값을 직접 가질 수 없다.
이 때, CLR(Common Language Runtime)이 num의 값을 힙 영역에 새로 복사해서, 그 참조를 obj에 저장한다.
결국 obj는 int 값을 담은 객체를 가리키게 된다.
동작 구조
값 타입(예: int, double, struct 등)을 object, 인터페이스 타입 등에 할당하거나, 메서드에 파라미터로 넘길 때 박싱 발생.
박싱이 일어나면 값이 힙에 새로운 객체로 복사됨.
이 과정에서 런타임 오버헤드(추가적인 메모리 사용 및 성능 저하)가 발생할 수 있음.
언박싱은 참조 타입(object 등)에 저장된 값을 원래의 값 타입으로 다시 꺼내오는 과정이다.
즉, 힙에 저장된 값을 다시 스택에 복사하는 것.
예시
object obj = 123; // 박싱
int num = (int)obj; // 언박싱
obj는 힙에 저장된 int 값을 가리킨다.
(int)obj를 통해 언박싱을 수행하면, 힙에 있는 int 값이 다시 스택에 복사된다.
반드시 명시적 형변환(캐스팅)이 필요하다. (암시적으로 불가능)
동작 구조
언박싱 시, object(혹은 인터페이스)의 참조가 원래의 값 타입인지 검사한다.
만약 타입이 다르면 InvalidCastException이 발생한다.
타입이 맞으면, 힙에 있던 값을 스택에 복사.
object obj = 123;
double d = (double)obj; // 예외 발생
가급적 박싱/언박싱을 피하기 위해 제네릭, 구체적 타입 사용을 권장한다.
내부 동작, 성능 이슈, 예외 발생 케이스까지 잘 이해해야 효율적이고 안정적인 C# 코드를 작성할 수 있다.