.NET Framework에서는 모든 타입의 최상위 타입을 참조타입인 System.Object로 정의하고 있다.
object는 참조형식이 때문에 힙에 데이터를 할당한다.
반면, int나 double은 값 형식이기 때문에 스택에 데이터를 할당하며, 다형적이지 못하다.
이 두가지는 양립하는 것 처럼 보이지만 앞서 모든 타입의 최상위 타입은 참조형식인 System.Object를 상속받는다고 했다. 어떻게 그럴 수 있을까?
.NET Framework에서는 박싱(Boxing)과 언박싱(Unboxing)이라는 방법을 통해 이 두가지 서로 다른 타입을 이어준다.
int firstParam = 5;
int secondParam = 10;
int thirdParam = 15;
Console.WriteLine("{0} {1} {2}", firstParam, secondParam, thirdParam);
위와 같은 예제에서 실제로 Console.WriteLine에 들어가는 인자들은 object 배열이지만, 입력되는 값은 정수형 값 타입이다.
string으로 변환되기 위해서는 박싱을 해야한다.
박싱의 과정은 다음과 유사하다고 보면된다.
int i = 25;
object o = i; // boxing
Console.WriteLine(o.ToString());
언박싱의 경우
object firstParam = 5;
object o = firstParam;
int i = (int)o; //unboxing
string output = i.ToString();
값 형식을 참조형식으로 변환하게 되면 완전히 새로운 객체를 생성하게 되므로 성능상 취약점을 갖는다.
따라서, 값 타입의 객체를 직접 전달하지 말고, ToString()을 활용하여 문자열 인스턴스를 전달하는 게 좋다.
System.Collections 대신 System.Collections.Generic
박싱과 언박싱을 피할 수 있는 다른 규칙은 가능한 .NET 1.x의 System.Collections을 사용하는 것을 피하고, .NET 2.0에 추가된 Generic 컬렉션을 이용하는 것이다.
System.Collections의 ArrayList를 사용하는 예를 보자.
ArrayList arrList = new ArrayList();
arrList.Add(15);
ArrayList의 Add 메소드가 매개변수로 object 타입을 받기 때문에 위와 같은 코드에서는 필연적으로 박싱이 일어난다.
List<int> intList = new List<int>();
intList.Add(15);
위와 같이 제네릭 컬렉션인 List를 활용하자.
References
빌 와그너 (2017), Effective C# (3rd Edition), 한빛미디어
'아카이빙 > C#' 카테고리의 다른 글
[Effective C#] 불필요한 객체를 만들지 말라 (0) | 2018.08.11 |
---|---|
[Effective C#] string.Format()을 보간 문자열로 대체하라 (0) | 2018.06.30 |
[C#] LINQ (0) | 2018.06.26 |
[C#] 람다식 (Lambda Expression) (0) | 2018.06.26 |
[C#] 이벤트와 델리게이트 (0) | 2018.06.25 |