개발/C#

[Effective C#] Boxing & Unboxing 정리 (+값타입/참조타입 정리)

huiyu 2021. 2. 11. 06:00

 .Net framework는 모든 타입의 최상위 타입을 System.Object로 정의하며 이 Object는 모든 타입의 베이스클래스이다. 타입에는 값타입, 참조타입, 포인터 타입등으로 나뉘어진다.

값 타입

 주로 값을 저장할 때 쓰는 저장소, 다형적이지 못하다. 값 타입은 스택영역에 저장된다. (int, char, double ...)
값타입은 Object를 상속받은 System.ValueType을 상속받은 구조체이다.(System.ValueType)

int -> System.Int32로 정의. 상속관계는 Object->ValueType->Int32 (Int32 구조체)
char -> System.Char로 정의. 상속관계는 Object->ValueType->Char(Char 구조체)

참조타입

모든 타입의 base class인 System.Object를 상속받으며, 힙 영역에 저장된다. 값형식은 해당 데이터에 직접 값이 저장된다면, 참조 타입은 데이터(개체)에 대한 참조가 저장된다.

참조타입은 처음 변수를 선언하면 값타입과 달리 메모리가 생성되지 않는다.

Class A
{
}

A a = null; // 메모리 생성되지 않음.

이후 A를 생성한다면 실제 생성된 A는 힙에 메모리를 할당, a는 그 값에 대한 참조만 스택에 저장한다.

A a = new A(); // 메모리 생성, 변수 a는 생성된 A의 참조(주소)만 갖게 됨.

a를 새로운 aa에 할당한다면 새로운 메모리를 할당하지 않고 참조하는 값만 복사.

A aa = a; // 새로운 메모리를 할당하지 않고, a의 참조값을 갖는 값만 복사함.

-> 참고 : C# 참조형식

Boxing(박싱)

- 값 타입의 객체를 참조 타입(Object)로 변환

int i = 123;
object o = i; //박싱
Console.WriteLine(o.ToString());

-> 단순한 형변환같지만 값타입은 스택에 저장되어 있고 참조타입은 힙에 저장되어 있다. 그래서 위 과정을 수행하기 위해선 스택에 저장된 값타입을 힙타입으로 복사가 한번 일어난다. 그리고 힙에 복사된 이 영역을 참조타입이 가리키게 되는 일을 수행한다.

Unboxing(언박싱)

- 참조타입을 값타입으로 변환

int i = 123;      // a value type
object o = i;     // boxing
int j = (int)o;   // unboxing

-> 박싱과 반대로, 힙에 있던 데이터를 다시 스택으로 복사가 일어난다.

* 박싱과 언박싱은 변환 과정에서 스택<->힙 과정에 복사가 일어날 뿐만 아니라, 복사 후 불필요한 가비지도 남아 성능상에 문제가 발생할 수도 있다. 가능한 박싱과 언박싱을 최소화하여 구현하는게 좋다. (MSDN 성능 팁)

 

 

[참고]
Effective C# -아이템9:박싱과 언박싱을 최소화하라
MSDN - boxing 및 unboxing (C# 프로그래밍 가이드) : 링크

728x90
반응형