Notice
Recent Posts
Recent Comments
Link
«   2025/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
Tags more
Archives
Today
Total
관리 메뉴

맛있는 개발노트 (맛과 개발을 함께)

C# 세미나 자료: 값 형식과 참조 형식 본문

C# 학습/C# 언어의 기초

C# 세미나 자료: 값 형식과 참조 형식

DevGourmet 2025. 4. 7. 11:24

1. 개요

C#에서 **값 형식(Value Type)**과 **참조 형식(Reference Type)**은 메모리 처리 방식과 동작에 있어 중요한 차이를 보입니다. 본 세미나에서는 두 형식의 차이점, 사용 방법, 메모리 구조, 복사 방식 및 실무 활용법 등을 초급~고급 단계로 나누어 설명합니다.


2. 기본 이론

2.1 값 형식 (Value Type)

  • 스택(Stack) 메모리에 저장
  • 데이터를 직접 담음
  • 복사 시 값 자체가 복사
  • 기본 예시: int, float, bool, char, struct, enum

2.2 참조 형식 (Reference Type)

  • 힙(Heap) 메모리에 저장
  • 데이터의 참조(주소)를 저장
  • 복사 시 참조(주소)가 복사
  • 기본 예시: string, class, object, interface, delegate

3. 단계별 설명

3.1 초급: 기본 개념 이해

예시 코드

int a = 10;
int b = a;      // b는 a의 값을 복사
b = 20;
Console.WriteLine(a); // 출력: 10

class Person {
    public string Name;
}

Person p1 = new Person();
p1.Name = "홍길동";
Person p2 = p1;
p2.Name = "이영희";
Console.WriteLine(p1.Name); // 출력: 이영희

주의사항

  • 값 형식은 복사된 값이 서로 독립적으로 존재
  • 참조 형식은 같은 객체를 가리키므로 한 쪽을 수정하면 다른 쪽도 영향 받음

3.2 중급: 구조체와 클래스 차이, 메서드 전달

구조체 vs 클래스 비교

항목구조체 (struct)클래스 (class)

저장 위치 스택
상속 불가능 가능
기본 상속 System.ValueType System.Object
기본 용도 가벼운 데이터 구조 복잡한 객체

메서드 전달 예시

void ModifyValue(int x)
{
    x += 10;
}

void ModifyRef(Person p)
{
    p.Name = "수정됨";
}

int num = 5;
ModifyValue(num);
Console.WriteLine(num); // 출력: 5

Person p = new Person { Name = "초기값" };
ModifyRef(p);
Console.WriteLine(p.Name); // 출력: 수정됨

  • 값 형식은 out/ref로 전달하지 않으면 복사본 처리
  • 참조 형식은 항상 참조로 전달되며, 내부 값 변경 가능

3.3 고급: boxing/unboxing, nullable, 복사 전략

Boxing / Unboxing

  • Boxing: 값 형식을 참조 형식으로 변환 (object에 할당)
  • Unboxing: 참조 형식을 다시 값 형식으로 변환
int i = 123;
object o = i;         // Boxing
int j = (int)o;       // Unboxing

Nullable 값 형식

  • 값 형식은 기본적으로 null 불가 → ?를 사용하면 null 허용
int? age = null;
if (age.HasValue)
    Console.WriteLine(age.Value);

깊은 복사와 얕은 복사

  • 참조 형식을 복사할 때 복제 방식 결정 필요
Person original = new Person { Name = "원본" };
Person shallow = original;          // 얕은 복사
Person deep = new Person { Name = original.Name }; // 깊은 복사

4. 결론

  • 값 형식과 참조 형식은 메모리 구조, 복사 방식, 데이터 전달 방식에서 차이가 있음
  • 구조체와 클래스의 사용 목적을 명확히 해야 성능과 안정성 향상
  • Boxing/Unboxing은 성능 이슈가 있으므로 자주 사용은 피해야 함
  • 실무에서는 깊은 복사/얕은 복사 여부에 따라 버그가 발생할 수 있으므로 주의

5. Q&A

  • Q: string은 값 형식인가요 참조 형식인가요? A: 참조 형식이지만 불변(immutable) 특성을 가지므로 값 형식처럼 사용됨
  • Q: 구조체에 메서드나 속성을 정의할 수 있나요? A: 가능합니다. 클래스처럼 멤버를 정의할 수 있습니다.
  • Q: 참조 형식을 복사할 때 안전하게 복사하려면? A: 깊은 복사(Deep Copy)를 수동 구현하거나, ICloneable 인터페이스를 활용합니다.

감사합니다!