Game Development, 게임개발/개발

C#에서의 값 형식, 참조 형식, 박싱(Boxing), 언박싱(Unboxing) [Unity]

게임이 더 좋아 2022. 4. 5. 23:37
반응형
728x170

 

C#에는 2가지 데이터 형식이 존재한다.

중요하다고 볼 수 있는 점은 대입 연산자 과정에 있다.

더욱이 복사 연산이 될 때다.

 

이 차이점은 이들 형식이 복사되는 방식에 따라 나뉘게 된다.

 

값형식의 데이터는 항상 값으로 복사되지만, 참조형식 데이터는 항상 참조로 복사된다.

알아보자

 

참고로 

값 형식은 얕은 복사(Shallow)

참조 형식은 깊은 복사(Deep)

 


 

기본 제공 데이터 형식 중 하나 또는 사용자 정의 구조체를 사용하여 선언된 변수는 값 형식을 가진다.

** 예외적으로 string 타입은 참조 형식이다.

 

기본 제공 타입은

이정도?

bool, char, byte, decimal, double, enum, float, int long, short, sbyte, struct, uint, ulong, ushort


 

**Stack

값 형식은 스택에 할당된 메모리에 데이터를 저장한다.

다시 말해서 해당 변수가 정의된 메서드의 실행이 종료되어 변수가 범위를 벗어나면 값이 스택에서 삭제된다.

** 또는 블록을 벗어남

 

당연히 스택을 사용하면 메모리 해제가 자유롭지만 해당 생명주기(life cycle)에 제약이 생긴다.

즉, 서로 다른 클래스 간에 데이터를 공유하기엔 적절하지 못한 방법이다.

 


 

**Heap

 

클래스 또는 배열의 인스턴스와 같은 참조 형식은 힙이라는 다른 메모리 영역에 할당된다.

타입을 말하자면 이정도?

class, interface, delegate, object, string

 

예를 들어서 배열을 만든다면 

int[] arr = new int[10001];

 

이런 식으로 new 같이 메모리를 할당받는 느낌?

 

이 메모리는 메서드가 종료되어도 자동으로 반환되지 않는다.

C#의 Garbage Collection 시스템에서 세대를 거쳐 참조를 하지 않게 되면 메모리로 다시 회수된다.

메모리가 힙에 남는 것이 꼭 단점만은 아니다.

참조 형식으로 선언하면 오버헤드가 커지지만 참조 형식은 다른 클래스에서 접근할 수 있다.

 


 

그렇다면 박싱 언박싱이 어디서 나오느냐?

 

바로 여기서 나온다.

Boxing은 값 형식을 참조 형식으로 변환하는 과정을 말한다.

변수를 boxing하면 힙의 새 복사본을 가리키는 참조 변수가 만들어진다.

-> C++의 참조변수와 비슷하다.

 

예를 들면 참조 변수는 개체이므로 모든 개체가 상속하는 모든 메서드(예: ToString())를 사용할 수 있다.

 
int i = 67;                              // i is a value type
object o = i;                            // i is boxed
System.Console.WriteLine(i.ToString());  // i is boxed

 

이와는 반대로 ArrayList를 사용하여 정수를 저장하는 것과 같이 개체와 함께 사용하도록 디자인된 클래스를 사용하면 unboxing이 수행된다.

-> 컨테이너에 값 형식이 담겨져 있다면..?

 

정수를 ArrayList에 저장하면 정수가 boxing된다.

다시 ArrayList에서 정수를 검색할 때는 unboxing되어야 한다.

 
 
System.Collections.ArrayList list = new System.Collections.ArrayList();  // list is a reference type
int n = 67;                              // n is a value type
list.Add(n);                             // n is boxed
n = (int)list[0];                        // list[0] is unboxed

 


 

C++에도 있는 방식이다.

다만 따로 박싱 언박싱이라는 용어는 쓰지 않는 듯하다.

C# 에서 박싱, 언박싱이 중요한 이유는 참조형식은 힙에 저장되기 때문이다.

즉, 우리가 직접 해제하는 것이 아닌 Garbage Collection에게 맡기기 때문에

C++과는 다르게 오버헤드가 크게 생길 수 있다.

 

MSDN의 문서에서 보자면

 

 

This can take up to 20 times longer than a simple reference assignment. 

When unboxing, the casting process can take four times as long as an assignment.




 

 

반응형
그리드형