본문 바로가기

C#/이것이 C#이다

5장. 값 형식과 참조 형식, 박싱과 언박싱

반응형

메모리


메모리에 값이 저장되는 과정을 살펴보자.

우선 C#의 모든 Type은 Object를 상속받는다.

1) 값 형식

값 형식이란, 변수가 을 담는 형식을 뜻한다.

기본적으로 스택 메모리에 할당된다.

 

 

2) 참조 형식

참조 형식이란, 변수가 값 대신 값의 위치(참조)를 담는 형식을 뜻한다.

힙 메모리 영역에 할당된다.

참고로 참조 형식은 null 할당이 가능하다.

 


메모리 할당


코드데이터 영역은 컴파일 시 크기가 지정되고,

과 스택 영역은 런타임 시 크기가 지정된다.


박싱과 언박싱


1) 박싱: 값 타입 객체를 참조 타입으로 변환

2) 언박싱: 참조 타입을 값 타입으로 변환

 

https://velog.io/@yongseok1000/%EB%B3%80%EC%88%98-%ED%95%A8%EC%88%98-%EB%81%8C%EC%96%B4%EB%8B%A4-%EC%93%B0%EB%8A%94%EB%B2%95

 

[유니티 C#] 박싱과 언박싱

Boxing, Unboxing

velog.io

이는 단순 참조 할당보다 최대 20배 더 오래 걸릴 수 있으며,
언박싱할 때 캐스팅 프로세스는 할당보다 4배 더 오래 걸릴 수 있다.

 

박싱

int i = 123;
object obj = i;				// 암시적 박싱
object obj = (object)i;		// 명시적 박싱

 

언박싱

int i = 123;			// 갑 형식
object obj = i;			// 암시적 박싱
int j = (int)obj;		// 명시적 언박싱


코드 실습: 박싱과 언박싱


queue1은 모든 형식의 객체(object)를 담을 수 있는 큐입니다.

queue2는 string 형식의 객체만을 담을 수 있는 큐입니다.

 

 

1) 1번과 2번의 차이

queue1에 10이라는 int형 객체를 담았습니다. 그러나 queue1은 object 형 객체를 담는 큐이므로,

int형인 10이 object형으로 "박싱"됩니다.

스택 메모리에 참조값이 저장되고, 해당 주소의 힙 메모리에 가보면 10이 저장되어 있습니다.

 

queue2에는 "10"이라는 string형 객체를 담았습니다. queue2는 string 형 객체를 담는 큐이므로,

string형인 "10"이 힙 메모리에 저장됩니다. 그러나 이것은 "박싱"은 아닙니다.

박싱은 값 형식을 참조 형식으로 변환하는 것이기 때문입니다.

여기서는 참조 형식을 참조 형식에 담았으므로 박싱이 아닙니다.

 

https://pyowatermelon.tistory.com/81

 

4/18 : TIL | Object, 참조/값 형식, 박싱 - 언박싱의 개념

Object C#의 데이터 형식은 크게 4가지이다. 숫자, 논리, 문자열, 오브젝트 형식이 있다. 이 중 특별하게 Object 형식은 영단어 뜻 '객체' 그대로 어떤 데이터든지 다룰 수 있는 형식이다. Object가 특별

pyowatermelon.tistory.com

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Queue queue1 = new Queue(); //큐, object 값을 담음
            Queue<string> queue2 = new Queue<string>(); //제네릭 큐, string 값을 담음

            //1
            queue1.Enqueue(10); //박싱

            //2
            queue2.Enqueue("10"); //박싱 X

            //3
            var result1 = queue1.Dequeue(); //언박싱 X
            //int num = result1; // 언박싱 X, 오류 발생
            int num = (int)result1; // 언박싱

            //4
            var result2 = queue2.Dequeue(); //언박싱 X

            Console.WriteLine(result1.GetType().Name);
            Console.WriteLine(result2.GetType().Name);
            Console.ReadLine();
        }
    }
}

object 형식을 int 형식으로 변환할 수 없다는 오류 메시지가 뜬다. 그렇다면

답은 이렇게 된다.

 

2) 3번과 4번의 차이

queue1에 담긴 객체를 꺼냅니다. 힙 메모리에 저장되어있던  object 형식인 10을 꺼내 result에 담습니다.

이때 result 또한 object 형식으로, var가 10의 형식을 파악하여 object형으로 힙 메모리에 저장합니다.

그러나 이것은 언박싱은 아닙니다. 참조 형식이었던 object가 참조형식인 object가 된 것이기 때문입니다.

 

이것이 언박싱이 되려면 코드를

var result = (int)Queue1.Dequeue(); 

위와 같이 수정해야 할 것입니다.

 

다음으로 queue2에 담긴 객체를 꺼냅니다. 힙 메모리에 저장되어있던 "10"을 꺼내 result에 담습니다.

이때 result는 참조 형식으로, var가 "10"의 형식을 파악하여 string 형으로 힙 메모리에 저장합니다.

그러나 이것은 참조 형식을 값 형식으로 변환하는 언박싱은 아닙니다. 참조 형식이 참조 형식이 된 것이기 때문입니다.

반응형