C#

2. 데이터의 종류(4) - object, 상수, 열거, var

루체도 2020. 1. 25. 23:20

object형식

물건, 객체라는 뜻이다. object 형식은 어떤 데이터든지 다룰 수 있는 데이터 형식

object형식이 다른 데이터 형식을 다룰 수 있는 이유는 "상속"때문이다.

다시 말하면 object 형식이 모든 데이터 형식의 조상이다.

따라서 컴파일러는 어떤 형식의 데이터라도 object에 담아 처리할 수 있다.

이렇게 모든 데이터를 다루는 매커니즘을 박싱언박싱이라 한다.

 

박싱과 언박싱

object형식은 참조 형식이라 힙에 데이터를 할당한다.

그런데 값 형식의 데이터를 객체에 담았을 경우 어느 메모리에 데이터가 할당될까?

값 형식의 데이터를 힙에 할당하기 위해 "박싱" 기능이 있다.

object a = 20;

20은 상자에 담겨 힙에 할당되고 a는 그 주소를 참조하게 된다.

이제 이 박싱된 데이터를 값 형식 객체에 다시 할당해야 할 경우에는 다음 처럼하면 된다.

object a = 20;
int b = (int)a;

박싱되어있는 값을 꺼내 값 형식 변수에 저장하는 과정을 "언박싱" 이라고 한다.

 

상수 형식

변수와는 달리 안에 담긴 데이터를 바꿀 수 없는 메모리 공간

상수의 선언은 변수의 선언과 비슷하지만 데이터 형식 앞에 const 키워드가 위치하고

상수가 가져야 한느 데이터를 반드시 대입을 해줘야 하는 점이 다르다.

const 자료형 상수명 = 값;
//////////////////////
const int a = 3;
const double b = 3.14;
const string c = "abcdef";

 

열거 형식

같은 범주에 속하는 여러 개의 상수를 선언할 때 사용

열거 형식도 상수지만 const 키워드를 사용하지는 않고 enum 키워드를 사용한다.

enum 열거 형식명 : 기반 자료형 { 상수1, 상수2, 상수3, ....}
enum DialogResult {YES,NO,CANCEL,CONFIRM,OK}

기반 자료형은 정수 계열만 사용할 수 있으며, 생략할 경우 컴파일러가 int를 기반자료형으로 사용한다.

이  DialogResult 선언에는 상수들이 어떤 값도 할당받지 않았다.

이런 경우에 YES = 0, NO = 1 이런식으로 1씩 차례차례 증가한 값을 컴파일러가 자동으로 할당한다.

이런식으로 설계된 이유는 열거 형식의 요소가 어떤 값을 갖느냐는 별 의미가 없기 때문이다.

열거 형식의 각 요소는 서로 중복되지 않는 값을 가지는데 의미가 있다.

 

열거 형식의 각 요소를 프로그래머가 원하는 값을 직접 대입할 수도 있다.

enum 열거형식명 { 상수1= 값1, 상수2= 값2, ...}

만약 상수2에 20을 넣고 그 다음 상수에 값을 할당하지 않으면 컴파일러가 알아서 1 증가한 값인 21을 할당하게 된다.

 

강력한 형식의 언어

C#은 변수나 상수에 대해 깐깐하게 형식 검사를 하는 강력한 형식의 언어이다,

강력한 형식 검사는 프로그래머의 실수를 줄여 주는 장점이 있다.

의도치 않은 형식의 데이터를 읽거나 할당하는 일을 막아준다.

C#은 강력한 형식 검사를 하는 언어이지만, var 키워드를 통해서 약한 형식 검사를 하는 언어의 편리함도 지원한다.

int, string 같은 명시적 형식 대신 var을 사용해서 변수를 선언하면 컴파일러가 자동으로 해당 변수의 형식을 지정

단, 선언과 동시에 초기화를 해줘야 한다. 그래야 컴파일러가 데이터 형식을 결정할 수 있다.

 

var 형식의 초기화

var a = 3; //a는 int 형식
var b = "Hello"; //b는 string 형식
var은 지역 변수로만 사용할 수 있다.
var 키워드로 필드를 선언하면 컴파일러가 무슨 형식인지 파악할 길이 없기 때문에 지역 변수로만 사용할 수 있다.

 

object 형식과 var 형식

object a = 20;

위 코드 object a = 20;은 컴파일되서 실행되면 CLR은 20을 박싱해서 힙에 넣어놓고 a가 힙을 가리키도록 만든다.

하지만 var a = 20;은 컴파일 시점에 컴파일러가 a에 적합한 데이터 형식을 파악해서 int a = 20;으로 바꿔 컴파일한다.

CLR이 해당 코드를 실행할 때는 a가 var로 선언되었는지 눈치채지 못하고 int 형식 객체 a에 20을 담아 스택에 올린다.