[문과 코린이의 IT 기록장] C# - 데이터 보관하기 2
(상수와 열거 형식, Nullable 형식, var : 데이터 형식(Data Type)을 알아서 파악하는 똑똑한 C# 컴파일러, 공용 형식 시스템)
1. 상수와 열겨 형식
- 변수 : 담고 있는 데이터를 얼마든지 변경할 수 있는 메모리 공간
- 상수, 열거 형식 : 변수와 달리, 안에 담긴 데이터를 절대 바꿀 수 없는 메모리 공간
* 프로그래머의 실수를 방지하기 위해, '값을 바꾸지 말아야 할 변수'를 정의하는 것.
1) 상수
[ 상수 선언 형식 ]
const 자료형 상수명 = 값 ; ex) const int a =3; const double b = 3.14; const string c = "abcdef"; |
ex )
2) 열거 형식 - 여러 개의 상수를 정리합니다.
- 프로그래밍을 하다 보면, 종류는 같지만 다른 값을 가지는 상수를 선언해야 할 경우가 가끔 있다.
ex) 사용자에게 메시지 박스를 띄워 응답을 받는 프로그램
* YES/NO, YES/NO/CANCEL ... 다양한 조합으로 선택 가능 : 이를 <사용자로부터 받는 응답>이라는 범주에 속한다는 의미에서 다음과 같이 선언할 수 있다.
const int RESULT_YES = 1; const int RESULT_NO = 2; const int RESULT_CONFIRM = 3; const int RESULT_CANCLE = 4; const int RESULT_OK = 5; |
- 수백개의 상수 중에서 만에 하나 중복되는 값을 지니는 상수들이 존재한다면, 프로그램에 문제가 생기게 된다.
ex) RESULT_YES와 RESULT_CANCEL이 모두 1이라는 값을 지닌다면?
- 열거 형식은 이러한 문제점들을 막아주는 장치이다.
: 같은 범주에 속하는 여러 개의 상수를 선언할 때 아주 유용하다.
: 열거 형식도 상수이긴 하지만 const 키워드를 사용하는 대신, enum 키워드를 사용한다.
enum 열거 형식명 : 기반 자료형 { 상수1, 상수2, 상수3, ... } // 이 형식은, 정수 계열 자료형(byte, sbyte, short, ushort, int, uint, long, ulong, char)만 사용할 수 있다. // 생략할 경우 컴파일러가 int를 기반자료형으로 사용한다.. |
- 열거 형식을 사용해서 위의 예시 <사용자로부터 받는 응답>을 작성해보면?
enum DialogResult { YES, NO, CANCEL, CONFIRM, OK } // 이렇게 선언하면, 첫번째 열거 형식 요소에는 0, 그 다음에는 1, 2, 3 ... 과 같이 1씩 증가하는 값을 컴파일러가 자동으로 할당한다. |
ex )
* 열거 형식은 어떤 요소가 어떤 값을 가지는지가 중요한게아니라, 서로 중복되지 않는 값을 갖게 하는데 의미를 갖는다.
- DialongResult는 열거 형식이다. 즉, 변수가 아닌, 새로운 형식이 만들어졌다는 것이다.
- 따라서, DialogResult 열거 형식의 변수를 선언하여, 값을 대입할 수 있다.
DialogResult result = DialogResult.YES; // DialogResult result = 0; 보다 더 코드 표현이 좋음 |
ex )
- 열거 형식의 각 요소는 기본적으로 컴파일러에게 값을 자동으로 할당받는다.
- 그러나 프로그래머가 원하는 값을 직접 대입할 수도 있다.
enum 열거형식명 { 상수1 = 값1, 상수2 = 값2, 상수3 = 값3, ... } |
- 열거 형식을 선언할 때, 첫 번째 요소에는 직접 프로그래머가 값을 할당하고, 두 번째 요소부터 엉떤 값도 할당하지 않으면, 컴파일러는 자동으로 +1의 값을 할당하기 시작한다.
enum 열거형식명 { YES = 10, NO, CANCEL, CONFIRM =50, OK } // NO는 11, CANCEL은 12, OK는 51 |
ex )
2. Nullable 형식
- C# 컴파일러는 메모리 공간에 반드시 어떤 값이든 넣도록 강제한다. 그렇게 하지 않으면, C#은 실행 파일을 내주지 않는다.
- 그러나, 프로그래밍을 하다 보면 어떤 값도 가지지 않는 변수가 필요할 경우가 있다. 그 때 필요한 형식은, 변수가 Null상태인, Nullable형식이다.
* Nullable = Null(비어 있는) + able(~될 수 있는)
1) Nullable 형식의 선언방법
데이터형식 ? 변수이름; ex ) int ? a = null; float ? b = null; double ? c = null; int d; // 컴파일 에러 발생 |
2) Nullable 형식의 속성
- 모든 Nullable 형식은, HasValue와 Value 두 가지 속성을 가지고 있다.
* HasValue 속성 : 해당 변수가 값을 갖고 있는지, 그렇지 않은지를 나타낸다.
* Value 속성 : 변수에 담겨있는 값을 나타낸다.
int ? a = null; Console.WirteLine(a.HasValue); // a.HasValue : a변수가 값을 가지고 있는가? -> Null이므로, False 출력 a= 37; Console.WriteLine(a.HasValue); // a.HasValue : a변수가 값을 가지고 있는가? -> 값을 가지고 있으므로, True 출력 Console.WirteLine(a.Value); // 37 출력 |
- 즉, Nullable 형식을 사용할 경우에는, HasValue 속성을 확인하거나 null과 같은지를 비교하여, 변수가 비어있는지 확인하는 절차가 필요하다.
ex) Nullable 형식을 테스트하는 예제 프로그램
3. var : 데이터 형식(Data Type)을 알아서 파악하는 똑똑한 C# 컴파일러
- C#은 변수나 상수에 대해 깐깐하게 검사를 해, 프로그래머의 실수를 줄여주는 강력한 형식의 언어이다.
- 그러나, 다양한 형식에 대해서 프로그래머가 알고 있어야 한다는, 불편함 또한 가지고 있다.
- 이러한 단점을 보완하기 위해, C#은 강력한 형식 검사를 하는 언어이지만, var 키워드를 통해 약한 형식 검사를 하는 언의 편리함 또한 지원한다.
ex) int, string과 같은 명시적 형식 대신, var를 사용해서 변수를 선언하면 컴파일러가 자동으로 해당 변수의 형식을 지정해준다.
// var은 선언과 동시에 초기화가 필요하다
// var은 지역 변수(코드 블록 안에서만)로만 사용할 수 있다.
var a = 3; // a는 int 형식 var b = "Hello"; // b는 string 형식 |
ex )
cf ) GetType() : Object의 인스턴스 타입을 가져온다.
[ var 형식 vs object 형식 ]
object a = 20; // 이 코드가 컴파일되어 실행되면, CLR은 20을 박싱해서 힙에 넣어놓고, a가 힙을 가리키도록 한다. var b = 30; // 컴파일 시점에 컴파일러가 b에 적합한 데이터 형식을 파악해서, int b = 30;이라고 바꿔 컴파일 한다. // 즉, CLR이 해당 코드를 실행할 때는, b가 var로 선언되었는지조차 눈치채지 못하고, b에 30을 담아 스택에 올린다. |
4. 공용 형식 시스템
[ 정리 ] - C#은 byte, int, float, string, object와 같이 다양한 기본 데이터 형식을 지원한다. 프로그래머는 이를 조합해서 복합 데이터 형식을 만들어 사용할 수 있다. - 또한, 스택/힙이라는 두 가지 메모리 영역을 활용해, 변수의 생명주기에 따라, 변수를 값 형식/참조 형식으로 만들어 사용할 수 있다. |
- 그러나, C#의 모든 데이터 형식 체계는 사실 C#고유의 것이 아니다.
- 공용 형식 시스템(CTS : Common Type System)이라는, .NET의 형식 체계 표준을 그대로 따르고 있을 뿐이다.
* 공용 형식 시스템 : 모두(.NET이 지원하는 모든 언어)가 함께 사용하는 데이터 형식 체계
** 마이크로소프트가 .NET에 공용 형식 시스템을 도입한 가장 큰 이유는, .NET 언어끼리 서로 호환성을 갖도록 하기 위해서이다.
- 즉, C#의 데이터 형식 체계가 CTS 표준을 따르고 있다는 것이다.
[ C#, C++, Visual Basic의 기본 데이터 형식 비교 표 ]
클래스 이름 | C# 형식 | C++ 형식 | Visual Basic 형식 |
System.Byte | byte | unsigned char | Byte |
System.SByte | sbyte | char | SByte |
System.Int16 | short | short | Short |
System.Int32 | int | int 또는 long | Integer |
System.Int64 | long | __int64 | Long |
System.UInt16 | ushort | unsigned short | UShort |
System.UInt32 | uint | unsigned int 또는 unsigned long | UInteger |
System.UInt64 | ulong | unsigned__int64 | ULong |
System.Single | float | float | Single |
System.Double | double | double | Double |
System.Char | char | wchar_t | Char |
System.Decimal | decimal | Decimal | Decimal |
System.IntPtr | x | x | x |
System.UIntPtr | x | x | x |
System.Object | object | Object* | Object |
System.String | string | String* | String |
- 공용 형식 시스템의 형식은 각 언어에서 코드에 그대로 사용할 수 있다.
ex )
[ GetType() 메소드와, ToString() 메소드 ] - 모든 데이터 형식은 object 형식으로부터 상속받는다. 상속을 하게 되면 부모로부터 가진 것을 모두 받는다. - 위의 예제 코드에서의 GetType()과 ToString() 메소드는 사실, System.Int32, int, System.String, string 형식이 object 형식으로부터 물려받아 가지고 있는 것이다. * GetType() : 해당 객체의 실제 데이터 형식을 알려준다. * ToString() : 해당 변수의 데이터를 문자열로 표시한다. |
* 유의사항 - 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다. - 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다. - 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :) |