C#에서 모든 데이터 형식은 object를 상속 받는다.
1. Boxing
Boxing은 Value Type(int, float, char, bool, struct, ...)의 데이터를 Reference Type(object, string, class, ...)으로 변환하는 프로세스이다.
int i = 1;
object o = i; // 암시적 Boxing
값 형식의 데이터는 메모리의 스택 영역에 할당되는데, Boxing을 통해 참조 타입인 object로 변환되면서 힙 영역에 복사된다.
# Boxing.cs
public class Boxing : MonoBehaviour
{
void Start()
{
int i = 1;
object o = i;
i = 2;
Debug.Log("i : " + i);
Debug.Log("o : " + o);
}
}
i를 object o로 boxing하면 힙 영역에 i의 값을 복사한다.
i와 o는 서로 다른 메모리 위치를 사용하기 때문에, 위 결과 다른 값을 갖게 된다.
# Boxing2.cs
public class Boxing2 : MonoBehaviour
{
void Start()
{
int a = 1;
int b = a;
object oa = a;
object ob = b;
Debug.Log("a == b : " + (a == b));
Debug.Log("oa == ob : " + (oa == ob));
}
}
object는 Reference Type으로 힙 영역에 할당된 메모리의 주소를 갖고있다.
Reference Type에 대한 '==' 연산자는 참조에 대한 비교로, oa와 ob는 다른 주소를 갖고 있으므로 False를 return한다. (메모리 위치의 값과는 상관없이)
2. Unboxing
Unboxing은 반대로 object 형식을 Value Type으로 변환하는 프로세스다.
int i = 1;
object o = i; // Boxing
o = 2;
int j = (int)o; // Unboxing
참조 타입인 Object가 값 형식 데이터로 Unboxing된다. 이때 Object가 참조하고 있는 메모리의 값을 스택 영역에 복사한다.
Unboxing은 Boxing된 데이터의 원래 타입으로 명시적인 형변환만 가능하다.
MSDN에 따르면 다음과 같은 연산 과정을 겪는다.
•개체 인스턴스가 지정한 값 형식을 boxing한 값인지 확인합니다.
•인스턴스의 값을 값 형식 변수에 복사합니다.
null에 대한 unboxing 시도는 NullReferenceException, 원래 값 형식과 다른 타입에 대한 참조는 InvalidCastException이 발생한다.
3. ArrayList
ArrayList는 복잡자료형 클래스로, 여러 타입의 데이터를 담을 수 있다.
Add 메서드는 object를 매개변수로 받는다.
public virtual int Add (object value);
ArrayList al = new ArrayList();
al.Add(1);
al.Add(0.1f);
al.Add("string");
파이썬의 List나 Dictionary처럼 자료형에 구애받지 않고 편리하게 사용할 수 있을 듯하나 지금은 권장되지 않는 방법이다.
MSDN의 ArrayList 설명에 다음과 같이 명시 되어있다.
⚠️ 중요
새 개발에는 클래스를 사용 하지 않는 것이 좋습니다 ArrayList . 대신 제네릭 클래스를 사용하는 것이 좋습니다 List<T>. ArrayList클래스는 개체의 유형이 다른 컬렉션을 포함 하도록 디자인 되었습니다. 그러나 항상 최상의 성능을 제공 하는 것은 아닙니다. 대신, 다음을 수행하는 것이 좋습니다.
•다른 유형의 개체 컬렉션의 경우 List<Object> (c #의 경우) 또는 List(Of Object) (Visual Basic)를 사용 합니다.
•개체의 유형이 같은 컬렉션의 경우 클래스를 사용 List<T> 합니다. 이러한 클래스의 상대적인 성능에 대 한 설명은 참조 항목의 성능 고려 사항 을 참조 하세요 List<T> . 제네릭이 아닌 컬렉션 형식 대신 제네릭 사용에 대 한 일반 정보는 GitHub에서 제네릭이 아닌 컬렉션을 사용 하지 않아야 합니다 .를 참조 하세요.
기본적으로 스택은 작고 빠르지만, 힙은 크고 느리다.
다시 말해 힙 영역에 메모리를 할당하는 것은 스택 영역을 사용하는 것보다 많은 비용이 소요된다. 또한 힙 영역에 할당된 메모리는 가비지 컬렉터가 따라 붙기 때문에 추가 비용도 발생한다.
ArrayList vs List<Object>
복잡자료형을 사용할 때 ArrayList 대신 Generic 클래스 List<object>를 사용하라고 되어있다.
두 방법 간 퍼포먼스 차이는 크게 없다.
다만 LINQ Extension Methods와 같이 Generic Class를 사용했을 경우 편리한 일이 많아 권장되는 것 같다.
참고1) MSDN Boxing 및 Unboxing(C# 프로그래밍 가이드) - https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/types/boxing-and-unboxing
참고2) IL2CPP 최적화 : 박싱(Boxing) 피하기 - https://blogs.unity3d.com/kr/2016/08/11/il2cpp-optimizations-avoid-boxing/
참고3) ArrayList vs List<object> - https://stackoverflow.com/questions/391088/arraylist-vs-listobject
'Unity & C#' 카테고리의 다른 글
Enter Play Mode, Domain Reload와 Scene Reload (0) | 2020.07.02 |
---|---|
Grid System (3) - A* Pathfinding (0) | 2020.05.30 |
Grid System (2) - 미로 만들기 (Maze Algorithm) (0) | 2020.05.22 |