본문 바로가기
C#

[C#] Boxing과 Unboxing의 고찰

by 대박플머 2014. 6. 11.

프로그래밍을 처음 배우면 보통 성능에는 관심이 없다. 

회사에 입사하면 성능을 따지는 경우가 대부분이다. 

그런데 가장 많이 간과하는 부분이 Boxing과 Unboxing이 아닐까 싶다. 

필자도 모르는 상태에서 프로그래밍을 하다 상사에게 듣고 검색에 검색을 통해 정확하게 이해할 수 있었다. 


Boxing과 Unboxing을 논하기 전에 먼저 알아야할 것이다. 

바로 값 형식과 참조 형식에 관한 것이다. 

-------------------------------------             MSDN 참조         ------------------------------------------------

※ 값 형식 

값 형식은 다음과 같은 두 개의 기본 범주로 구성됩니다.

구조체는 다음과 같은 범주로 구분할 수 있습니다.

값 형식을 기반으로 한 변수에는 값이 직접 포함됩니다. 값 형식 변수 하나를 다른 변수에 대입하면 변수에 포함된 값이 복사됩니다. 이는 참조 형식 변수를 대입하는 경우와 다릅니다. 참조 형식 변수의 경우 개체 자체가 아니라 개체에 대한 참조가 복사됩니다.

모든 값 형식은 암시적으로 System.ValueType에서 파생됩니다.

참조 형식과 달리 값 형식에서는 새 형식을 파생시킬 수 없습니다. 그러나 구조체는 참조 형식과 마찬가지로 인터페이스를 구현할 수 있습니다.

참조 형식과 달리 값 형식에는 null 값이 포함될 수 없습니다. 그러나의 nullable 형식 은 기능에 할당 될 값 형식에 대해 허용 하지 null.

각 값 형식에는 해당 형식의 기본값을 초기화하는 암시적 기본 생성자가 있습니다. 

※ 참조 형식

참조 형식의 변수에는 데이터(개체)에 대한 참조가 저장된다. 참조 형식에서는 두 가지 변수가 같은 개체를 참조할 수 있으므로 한 변수에 대한 작업이 다른 변수에서 참조하는 개체에 영향을 미칠 수 있습니다. 값 형식에서는 각 변수에 데이터의 자체 사본이 들어 있으며 한 변수의 작업이 다른 변수에 영향을 미칠 수 없습니다

다음 키워드는 참조 형식을 선언하는 데 사용됩니다.

C#는 다음과 같은 기본 참조 형식도 제공합니다.

--------------------------------------------------------------------------------------------------------------







그럼 이제 본격적으로 Boxing과 Unboxing에 대해 이야기를 해보자.....

위에서 보는 바와 같이 값 형식과 참조 형식이 있다. 그렇기 때문에 두형식간의 형식 변화가 필요한데 그 형식 변화를 Boxing과 UnBoxing이라고 한다. 

Boxing : 값 형식 -> 참조 형식 (암시적)

Unboxing : 참조 형식 -> 값 형식 (명시적)

ex) Boxing, Unboxing

1
2
3
4
5
 
int i = 123;      // a value type
object o = i;     // boxing
int j = (int)o;   // unboxing
 

이제 Boxing과 Unboxing에 대해 자세히 이야기 해보자. 

※ Boxing
위의 예제에서 보면 아무 문제가 없어 보인다. 
그리고 우리들은 값을 다양하게 형태의 변수로 받기 위해 object로 형변환을 자주 하는 편이다. 

그런데 어떤 점이 문제가 될까? 
이것은 내부적으로 돌아가는 로직을 봐야 한다. 

MSDN에서의 확인할 수 있는 Boxing 과정을 표현한 이미지이다. 

Boxing은 가비지가 수집되는 힙에 값 형식을 저장하는 데 사용된다.
Boxing은 값 형식을 참조 형식으로 변환하는 것이다. 
내부에서 일어나는 일을 순차적으로 보게 되면
첫번째로 힙에 Object가 참조할 int형 변수를 만들게 된다. 
두번째로 힙에 만들어진 int형 변수를 Object가 주소값을 저장한다.
두번째로 힙에 만들어진 int형 변수에 값을 복사한다. 

그냥 이렇게만 보면 큰 문제가 되지 않는 것처럼 보인다. 하지만 한번 생각봐야 한다. 
내가 코딩한건 단순히 "Object o = i;뿐이다. 
그런데 힙에 int형 변수를 생성한고 하라는 일은 가장 뒷전이다. 
 
잘 이해가 안간다면 이 소스를 보면 아주 명확하고 명료하게 이해가 갈 것이다. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TestBoxing
{
    static void Main()
    {
        int i = 123;
 
        // Boxing copies the value of i into object o.
        object o = i;  
 
        // Change the value of i.
        i = 456;  
 
        // The change in i does not effect the value stored in o.
        System.Console.WriteLine("The value-type value = {0}", i);
        System.Console.WriteLine("The object-type value = {0}", o);
    }
}
/* Output:
    The value-type value = 456
    The object-type value = 123
*/


아주 Simple하지만 결과 값은 아주 충격적이다. 

이것을 ArrayList 같은 녀석에서 사용하면 아주 그냥 가비지가 뻗을 수도 있다.(실제로 그럴 일은 없겠지만 성능 저하는 명백하게 확인 할 수 있을 것이다.)

※ Unboxing

UnBoxing은 크게 할 말이 없는 것갔다. 내부적으로 돌아가는 걸 봤다면 Unboxing가 어느정도 짐작이 되기 때문이다. 
우선 그림하나 보고 시작하자. 

내부 돌아가는 로직은

첫째. 개체 인스턴스가 지정한 값 형식을 boxing한 값인지 확인해야 한다. 

두번째. 인스턴스의 값을 값 형식 변수에 복사합니다.

이다. 

유의해서 볼 부분은 첫째인것 같다. 꼭 확인들 하시길 바란다. 

참고로 이렇게 Unboxing을 할경우 예외가 발생할 수 있다. 

호환되지 않는 값 형식에 대한 참조를 unboxing하려고 하면 InvalidCastException이 발생한다. 

간단하게 Try Catch 사용해주면 땡큐 하시겠다. 


이상 끝...



'C#' 카테고리의 다른 글

[C#] 내부 클래스  (1) 2014.06.16
[C#] 소멸자 Finalize  (0) 2014.06.13
[C#] Delegate 사용법  (0) 2014.06.12
[C#]명령 프롬프트에서 컴파일 하기 CSC.exe  (0) 2014.06.11
[c#] 파일 찾기 및 파일 내용 읽기 (File Search)  (0) 2014.06.02