값형은 변수에 값을 직접 저장하는 것을 말해요. 일반적으로 사용하는 int, float, double, bool등과 같은 기본데이터 타입들이 값형에 해당됩니다. string은 참조형이에요!!!
값형은 변수가 실제 데이터를 보유하고 있고 해당 변수를 다른 변수에 할당하거나 전달할 때는 값이 복사되므로 변수의 값을 수정해도 다른 변수에 영향을 주지 않아요.
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
참조형은 변수가 데이터에 대한 참조(메모리 주소)를 저장해요. 클래스, 배열, 인터페이스 등이 참조형에 해당됩니다. 변수가 실제 데이터를 가리키는 참조를 가지고 있고 해당 변수를 다른 변수에 할당하거나 전달할 때는 참조가 복사되기 때문에 데이터를 수정하게 되면 원본 데이터의 값이 변합니다.
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
박싱과 언박싱은 값형과 참조형 사이의 변환을 의미해요. 값형의 데이터를 참조형으로 바꾸는 것이 박싱, 박싱했던 것을 다시 원상태로 복귀시키는 것을 언박싱이라고 합니다.
스택에 있는 값형 변수의 값을 메모리의 힙 영역에 할당된 객체로 래핑해요. 박싱을 통해서 값형이 참조형의 특징을 갖게 되며, 참조형 변수로 다뤄질 수 있어요. 박싱된 값형은 참조로 전달되므로 메모리 오버헤드가 발생할 수 있습니다.
박싱된 객체에서 값을 추출하여 값형 변수에 할당합니다. 언박싱은 명시적으로 타입 캐스팅을 해야하며, 런타임에서 타입 검사가 이루어지는데 잘못된 형식으로 언박싱하면 런타임 에러가 발생할 수 있어요.
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
}
}
object는 .NET Commom Type System(CTS)의 일부이며, 모든 클래스의 직간접적인 상위클래스에요. 모든 클래스는 object에서 상속되며, object는 모든 형식을 참조할 수 있는 포괄적인 타입입니다.