티스토리 뷰

박싱과 언박싱 (Boxing & Unboxing)

박싱과 언박싱은 메모리 영역을 공부하면 알게되는 기법으로 값 형식의 데이터를 참조 형식으로 변환하는 과정을 박싱, 그 반대언박싱이라 한다.

 

 

박싱 (Boxing)

이해하기 쉽게 말하면, C#은 모든 객체의 최상단에 object가 있다. 즉, 모든 자료형은 object로 변환될 수 있다.

이러한 상황에서 int형 변수를 object로 바꾸어 보면 박싱이 되는 것이다.

 

박싱 (Boxing)
int value = 42; // 값 타입 변수를 선언하고 초기화
object boxedValue = value; // 값 타입을 참조 타입으로 박싱하여 저장

 

주의할 점은 단순히 스택에서 힙으로 값을 복사하는 것이 박싱이 아니다.

클래스 객체를 new로 만들어 힙영역에 할당되는데, 이때 해당  클래스 필드 값은 힙영역에 연속된 메모리 주소를 가지고 있지만 박싱이 되는 것이 아니다.

 

쉽게 말하면, 스택영역에서 힙영역으로 복사하는 것은 일종의 예제이고 힙영역 내부에서도 저장된 값을 참조 형식으로 변환하여 박싱할 수 있다.

 

즉, 메모리 영역의 차이라기보다 값을 참조 타입으로 변환하는 행위 자체를 박싱이라 하는 것이 맞다.

 

박싱 (Boxing)
using System;

class Program
{
    // 값 타입을 참조 타입으로 박싱
    public int value = 42;
    public object boxedValue;
    
    public Program()
    {
        boxedValue = value;
    }
}

class Runner
{
    static void Main(string[] args)
    {
    	// 힙영역에 클래스 객체 할당
        // 클래스 내부의 필드 변수들은 모두 힙영역에 할당되어 있음
        Program p = new Program();
        
        Console.WriteLine("Original value: " + p.value);
        Console.WriteLine("Boxed value: " + p.boxedValue);
    }
}
Original value: 42
Boxed value: 42

 

 

언박싱 (UnBoxing)

언박싱은 박싱의 반대로 박싱했던 것을 원 상태로 복원한다고 간단하게 생각하면 된다.

 

언박싱 (UnBoxing)
using System;

class Program
{
    // 값 타입을 참조 타입으로 박싱
    public int value = 42;
    public object boxedValue;

    // 박싱된 값 언박싱
    public int unboxedValue;
    
    public Program()
    {
        boxedValue = value;
        unboxedValue = (int)boxedValue;
    }
}

class Runner
{
    static void Main(string[] args)
    {
        Program p = new Program();
        
        Console.WriteLine("Original value: " + p.value);
        Console.WriteLine("Boxed value: " + p.boxedValue);
        Console.WriteLine("Unboxed value: " + p.unboxedValue);
    }
}
Original value: 42
Boxed value: 42
Unboxed value: 42

 

 


용도

박싱과 언박싱은 모든 타입을 활용하도록 만들어주어 잘 사용하면 범용적인 코드를 작성하게 해준다. 

 

다양한 유형의 데이터를 저장하는데 사용될 수 있고, 데이터 전송 및 저장에 사용되어 네트워크 통신에도 사용될 수 있다. 물론 불필요한 박싱의 사용은 성능저하를 일으킬 수 있다.

 

이쯤되면 "제네릭과 박싱/언박싱이 비슷한 일을 하지 않을까"하는 궁금증이 나올 수 있다.

 

제네릭과 박싱/언박싱

제네릭과 박싱/언박싱 둘 모두 다른 데이터 형식을 처리하는 방법을 제공하는 공통점이 있다. 이를 통해 좀더 유연한 코드를 작성하도록 도와준다.

 

제네릭컴파일 단에서 형식의 안정성을 보장하여 성능적으로 더 우수할 수 있다. 이에 따라 프로그래머가 직접 어떤 형태의 값이 전달되는지 알 수 있기에 가독성과 유지보수에도 많은 도움이 된다.

 

박싱/언박싱은 런타임 중 형변환 과정이 진행되어 성능 저하가 발생할 수 있다. 또한 추가적 예외처리를 개발하지 않는 이상 어떤 오류가 발생할지 모른다. 하지만 어떤 형태의 데이터(그렇게 만들일은 없지만)라도 박싱하여 사용할 수 있어 제네릭에 비해 형식에 대한 의존성이 훨씬 적어 더욱 데이터의 유연성을 보장할 수 있다.

 

타 블로그 예제
class Program
{
    static void Main(string[] args)
    {
        BoxingTest(1, "2", '3');
    }

    static void BoxingTest(params object[] args)
    {
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] is int)
            {
                int n = (int)args[i];
                Console.WriteLine(n + " is int");
            }
            else if (args[i] is char)
            {
                char c = (char)args[i];
                Console.WriteLine("'" + c + "' is char");
            }
            else if (args[i] is string)
            {
                string s = (string)args[i];
                Console.WriteLine('"' + s + "\" is string");
            }
        }
    }
}
1 is int
"2" is string
'3' is char

 

 


참고자료

 

[C#] 박싱(Boxing)과 언박싱(Unboxing)이란?

박싱(Boxing)과 언박싱(Unboxing)의 기본 개념과 사용법, 특징을 정리한다.

velog.io

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함