* 정의
C#에서는 값을 메모리에 저장하는 방법에 따라 데이터 타입을 크게 2가지로 분류한다.
- 1. 값 타입(Value type)
- 2. 참조 타입(Reference type)
* 값 타입(Value type)
- 정의
값 타입은 데이터의 값을 직접 메모리 공간에 보유하고 있는 경우를 의미한다.
값 타입 변수는 스택에 할당된 메모리에 데이터의 값을 직접 포함하는 변수를 의미한다.

- 특징
@ 스택에 데이터의 값을 저장하는 것은 효율적이지만, 값 타입의 제한된 생명주기는 다른 클래스와 데이터를 공유하기에 비효율적이다.
@ 각 값 타입 변수는 데이터의 고유한 복사본을 가지고 있기 때문에 (ref, out 키워드를 사용하지 않는다면)메소드를 통해서 이 변수를 변경할 수 없다. 값 타입 변수를 메소드를 통해 넘겨주게 되면 시스템은 이 변수를 복사하여 새롭게 변수를 만들게 된다.
@ 스코프를 빠져나가면 값이 스택에서 삭제된다.
@ C#의 값 타입은 다음 타입으로 분리된다.
- 단순 타입
- 열거형 타입
- 구조체 타입
- nullable 값 타입
@ 값 타입은 System.ValueType을 상속받는다.
@ 인터페이스를 제외하고 상속받을 수 없다. // IL에서 확인해보면 Sealed Class로 정의된다.
ildasm 툴로 확인한 값 타입

* 참조 타입(Reference type)
- 정의
값 타입가 다르게 데이터의 값을 직접 메모리에 저장하지 않는다. 대신 데이터의 값이 저장된 메모리를 저장한다. 간단히 참조 타입은 데이터의 값이 들어있는 다른 메모리 공간에 대한 포인터라고 생각하면 된다.

- 특징
@ 참조 타입은 데이터 값을 힙에 저장되고 해당 데이터 값이 존재하는 힙 메모리 주소를 스택에 저장한다.
@ 참조 타입을 선언하는 것은 오버헤드가 더 크지만 다른 클래스에서 접근할 수 있다는 장점이 있다.
@ 참조 타입을 사용하면 서로 다른 변수가 같은 객체를 참조하도록 할 수 있다. 참조 타입 변수를 메소드를 통해 넘겨주게 되면 이 데이터 값에 대한 새로운 복사본을 만들지 않는다. 대신 주소만 넘겨주게 된다. 만약 메소드에서 변수가 변경되면 원본 참조 타입에 영향을 준다.
@ 참조 타입 변수의 스코프를 벗어나게 되면 메모리는 바로 힙에 반환되지 않고 가비지 컬렉터가 해당 데이터가 더 이상 쓰이지 않을 때 수거하게 된다.
@ C#의 참조 타입은 다음 타입으로 분리된다.
- 클래스 타입
- 인터페이스 타입
- 배열 타입(요소가 값 타입인 경우 포함)
- 델리게이트 타입
- nullable 참조 타입 // C# 8.0부터 명시적으로 nullable을 표현하도록 하고 있다.
@ 참조 타입은 System.Object를 상속받는다.
@ 90%이상은 ref, out 키워드를 사용하나 안하나 똑같이 동작한다. (string과 같은 불변 참조 타입 제외)
ildasm 툴로 확인한 참조 타입

* 값 타입(Value type) vs 참조 타입(Reference type)
| 값 타입(Value type) | 참조 타입(Reference type) | |
| Base 클래스 | System.Object | System.ValueType |
| 정의 방법 | struct로 정의 | class로 정의 |
| 메소드에 참조로 넘겨주는 방법 | ref, out 키워드 사용 | 일반적으로 참조로 넘김 불변 참조 타입의 경우 ref, out 키워드를 사용 |
| 데이터 값의 저장 위치 | 스택 | 힙 |
| 할당 시 오버헤드 | 작다 | 크다 |
| 생명 주기 | 스코프를 빠져나가면 바로 삭제 | 스코프를 빠져나가면 가비지 컬렉터의 판단 하에 적절한 시점에 삭제 |
| 타입 종류 |
|
|
| 상속 가능 여부 | sealed class로 정의되기 때문에 인터페이스만 상속 가능하다. | 사용자가 sealed 로 정의하지 않았으면 어느 클래스든 상속 가능하다. |
'C#' 카테고리의 다른 글
| [C#] string vs StringBuilder (0) | 2022.06.28 |
|---|---|
| [C#] Nullable 타입 (0) | 2022.06.28 |
| [C#] .NET (0) | 2022.06.28 |
| [C#] abstract, sealed (0) | 2022.04.08 |
| [C#] 정적 클래스(static class) (0) | 2022.04.08 |