C# - 값 형과 참조 형

MothorMoth·2024년 4월 27일

C#

목록 보기
15/17
post-thumbnail

값 형과 참조 형

1. 값 형(Value Type)

  • 데이터를 직접 저장하며, 메모리의 스택에 할당된다. 예를 들어, 기본 데이터 타입인 int, double, float, bool 등이 있다.

  • 값 형 변수를 다른 변수에 할당하거나 전달할 때는 값이 복사되며, 값 형 변수의 수정은 해당 변수의 값만 변경하므로 다른 변수에 영향을 주지 않는다.

struct MyStruct
{
    public int Value;
}

MyStruct struct1 = new MyStruct();
struct1.Value = 10;

MyStruct struct2 = struct1; // struct2는 struct1의 값 복사
struct2.Value = 20;

Console.WriteLine(struct1.Value); // 출력: 10

2. 참조 형(Reference Type)

  • 데이터의 메모리 주소를 저장하며, 실제 데이터는 힙에 저장된다. 예를 들어, 배열, 클래스, 인터페이스 등이 있다.

  • 참조 형 변수를 다른 변수에 할당하거나 전달할 때는 참조가 복사되며, 참조 형 변수의 수정은 동일한 데이터를 가리키고 있는 다른 변수에 영향을 줄 수 있다.

class MyClass
{
    public int Value;
}

MyClass obj1 = new MyClass();
obj1.Value = 10;

MyClass obj2 = obj1; // obj2는 obj1과 동일한 객체를 참조

obj2.Value = 20;

Console.WriteLine(obj1.Value); // 출력: 20

3. 값 형과 참조 형의 차이점

  • 값 형은 실제 데이터를 변수에 저장하고, 참조 형은 데이터에 대한 참조를 변수에 저장한다.

  • 값 형은 변수 간의 값 복사가 이루어지고, 참조 형은 변수 간의 참조 복사가 이루어진다.

  • 값 형은 변수가 독립적으로 데이터를 가지며, 참조 형은 변수가 동일한 데이터를 참조한다.

박싱과 언박싱

1. 박싱(Boxing)

  • 박싱은 값 형을 참조 형으로 변환하는 과정으로, 값 형 변수의 데이터는 힙 영역에 할당된 객체로 래핑 되어 참조 형의 특징을 갖게 된다.

  • 박싱 된 값 형은 참조 형 변수로 다뤄지게 되며, 이로 인해 메모리 오버헤드가 발생할 수 있다.

메모리 오버헤드

  • 메모리 오버헤드는 추가적인 메모리 사용을 의미
  • 박싱 과정에서 값 형 데이터를 참조 형 객체로 변환할 때, 단순한 값 이상의 메모리가 필요하다.
  • 이 때문에 값의 저장과 관리에 필요한 메모리가 더 많아지며, 이 추가적인 메모리 사용이 오버헤드로 간주된다.
  • 박싱 된 객체는 값 자체뿐만 아니라 객체의 메타데이터와 관리 정보도 포함하기 때문에 이런 오버헤드가 발생한다.

2. 언박싱(Unboxing)

  • 언박싱은 박싱 된 참조 형 객체를 원래의 값 형으로 다시 변환하는 과정으로, 박싱 된 객체 내의 값을 추출해 값 형 변수에 할당한다.

  • 언박싱은 명시적으로 타입 캐스팅을 해야 하며, 런타임에 타입 검사가 이루어지기 때문에 타입이 일치하지 않을 경우 런타임 에러가 발생할 수 있다.

3. 박싱과 언박싱의 주요 특징

  • 박싱과 언박싱은 값 형과 참조 형 사이의 변환 작업이므로 성능에 영향을 미칠 수 있다. 반복적인 박싱과 언박싱은 성능 저하를 초래할 수 있으므로 주의해야 한다.

  • 박싱 된 객체는 힙 영역에 할당되므로, 가비지 컬렉션의 대상이 될 수 있어, 메모리 관리에 유의해야 한다.

  • 박싱 된 객체와 원래의 값 형은 서로 독립적이므로 값을 수정하더라도 상호 간에 영향을 주지 않는다.

    int num = 10;
    object obj = num; // num 값을 obj에 박싱
    
    num = 20; // num 값 변경
    
    Console.WriteLine(num);      // 출력: 20
    Console.WriteLine((int)obj); // 출력: 10

4. 사용 예제

using System;

class Program
{
    static void Main()
    {
        // 값 형
        int x = 10;
        int y = x;
        y = 20;
        Console.WriteLine("x: " + x); // 출력: 10
        Console.WriteLine("y: " + y); // 출력: 20

        // 참조 형
        int[] arr1 = new int[] { 1, 2, 3 };
        int[] arr2 = arr1;
        arr2[0] = 4;
        Console.WriteLine("arr1[0]: " + arr1[0]); // 출력: 4
        Console.WriteLine("arr2[0]: " + arr2[0]); // 출력: 4

        // 박싱과 언박싱
        int num1 = 10;
        object obj = num1; // 박싱
        int num2 = (int)obj; // 언박싱
        Console.WriteLine("num1: " + num1); // 출력: 10
        Console.WriteLine("num2: " + num2); // 출력: 10
    }
}
  • 리스트 활용 예시
List<object> myList = new List<object>();

// 박싱: 값 형식을 참조 형식으로 변환하여 리스트에 추가
int intValue = 10;
myList.Add(intValue); // int를 object로 박싱하여 추가

float floatValue = 3.14f;
myList.Add(floatValue); // float를 object로 박싱하여 추가

// 언박싱: 참조 형식을 값 형식으로 변환하여 사용
int value1 = (int)myList[0];      // object를 int로 언박싱
float value2 = (float)myList[1]; // object를 float로 언박싱

0개의 댓글