프로그래밍언어/C#

20200218[C#] Object형식, 박싱 언박싱

HJH0825 2020. 2. 18. 09:22

Object형식

Object형식은 모든 형식의 궁극적인 기반 클래스이다. 그 어떤 형식도 Object로 상향 캐스팅할 수 있다. 범용적으로 쓰이는 Stack구조를 살펴보자

        class Stack
        {
            public int Position;
            object[] array = new object[10];
            public void Push(object o)
            {
                array[Position++] = o;
            }
            public object Pop()
            {
                return array[Position--];
            }

        }

        static void Main(string[] args)
        {
            Stack stack = new Stack();
            stack.Push("Apple");
            string answer = (string)stack.Pop(); //하향 캐스팅
        }

그 어떤 형식의 인스턴스라도 push와 pop이 가능하다. 하지만 Object형식이기 때문에 Pop을 할 때는 명시적 캐스팅이 필요하다. 또, object는 하나의 클래스이며, 따라서 참조 형식이다. 그렇긴 하지만 int 같은 값 형식과 object사이의 캐스팅도 가능하다. c#의 이러한 특징을 형식 통합이라고 부른다.  

Object(참조) 형식도 int(값) 형식으로 변환이 가능하다.


박싱과 언박싱

위에서 살짝 언급한 내용으로 값 형식 인스턴스를 참조 형식 인스턴스로 변환하는 것을 박싱이다. 그럼 그 반대는? 언박싱이겠지라고 생각하는데 맞기는 하는데 한 가지 조건이 있다. 바로, 박싱 과정을 거친 객체를 되돌리는 것이 언박싱이다.

간단한 예제로 살펴보자

1.박싱

int x = 10;
object obj = x; //int 박싱

 

1.언박싱

int x = 10;
object obj = x; //int 박싱

int y = (int)obj; //int 언박싱

 

박싱은 그냥 하면 되고, 언박싱은 명시적 캐스팅이 필요하다. 이렇게 쉽게 참조 타입과 값 타입 사이에서 형식 변환을 쉽게 할 수 있다는 것은 매우 편리하다. 모든 함수와 자료구조 타입을 objct형식으로 만들어놓으면 캐스팅만 잘 사용한다면 코드 중복 없이 짧고 쉽게 설계가 가능할 것 같아 보인다. (이 세상에서 분명 공짜는 없다. 박싱과 언박싱에서는 단점이 있다. 다음에 설명 )

하지만, 기억해야 할 것은 objct는 참조 형식이고, int는 값 형식이다. 


박싱과 언박싱의 복사 의미론

 

박싱(값 -> 참조)은 값 형식 인스턴스를 새 객체로 복사하고, 언박싱(참조 -> 값)은 객체의 내용을 다시 값 형식 인스턴스로 복사한다. 말로 풀었을 때 무슨 소리인지 모르겠다. 이 과정은 어떤 과정인지 한 가지 예를 보고 살펴보자.

int i = 5;
object boxed = i;
i = 3;
Console.WriteLine(boxed);
Console.WriteLine(i);
Console.WriteLine(boxed);

  

먼저 출력 결과를 먼저 알려주면 위에서부터 5,3,5이다. 답을 맞혔다면 저 말을 이해가 된 것이다.  boxed와 i는 서로 다른 인스턴스 즉, "i는 boxed라는 새로운 인스턴스를 만들고 자신의 값을 복사했다."라는 말이다. 그래서 i의 값을 바꿔도 boxed의 값은 변경되지 않는다.