아카이빙/C#

[Effective C#] 박싱과 언박싱을 최소화하라

셩님 2018. 6. 30. 04:04

[Effective C#] 박싱과 언박싱을 최소화하라

  • .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