[C#] 변수와 데이터타입 (const/enum/Nullable/var)

2023. 4. 1. 16:17공부/C#

 

변수와 데이터타입 (const/enum/Nullable/var)

 

 

<목차>

1. 상수&열거형식 (const/enum)
2. Nullable 형식
3. var 형식

 

1. 상수&열거형식 (const/enum)

 

const와 enum은 각각 상수(Constants), 열거 형식(Enumerator)이라는 뜻이다. 변수는 저장된 데이터를 얼마든지 변경할 수 있는 메모리 공간이지만 상수와 열거형식은 안에 담긴 데이터를 바꿀 수 없다. 나중에 실수로라도 값이 바뀌면 안되는 중요한 데이터들은 상수나 열거형식을 사용하는 것이 바람직하다.

 

<상수 선언>
const 자료형 상수명 = 값;

<열거 형식 선언>
enum 열거형식명: 기반자료형 {상수1, 상수2, 상수3 ,···}

* 열거 형식은 정수 계열의 자료형에서만 사용할 수 있다. 자료형을 생략할 경우 컴파일러가 int를 기반 자료형으로 사용한다.

 

 

우선 예시 코드를 하나 살펴보자.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Program
    {
        static void Main(string[] args)
        {
            const int a = 30;
            const int b = 100;

            Console.WriteLine(a);
            Console.WriteLine(b);
        }
    }
}

 

<실행 결과>

 

 

 

평범하게 int로 선언했을때와 결과는 동일하다. 만약 상수의 값을 변경하려고 하면 어떤 일이 일어날까?

 

 

 

위와 같은 오류가 발생한다. 할당식의 왼쪽에는 상수가 들어올 수 없고, 이 말은 즉 상수의 값은 바꿀 수 없다는 이야기가 된다. 

 

 

이제 다음 코드를 살펴보자.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Program
    {
        enum Weapon { SWORD, STAFF, GUN, AXE, BOW };

        static void Main(string[] args)
        {
            Console.WriteLine((int)Weapon.SWORD);
            Console.WriteLine((int)Weapon.STAFF);
            Console.WriteLine((int)Weapon.GUN);
            Console.WriteLine((int)Weapon.AXE);
            Console.WriteLine((int)Weapon.BOW);
        }
    }
}

 

enum은 같은 범주에서 다른 값을 가져야 하는 상수를 선언할때 사용한다. 예를 들어, 한 게임에서 플레이어가 무기를 고를 수 있도록 프로그램을 짠다고 생각해보자. 검, 지팡이, 총, 도끼, 활 등... 이 무기들의 값은 바뀌어선 안되는 중요한 것들이니 상수로 선언한다.

 

const int Weapon_SWORD=1;
const int Weapon_STAFF=2;
const int Weapon_GUN=3;
const int Weapon_AXE=4;
const int Weapon_BOW=5;

 

일일히 상수를 만들어주는게 조금 번거롭기는 해도 여기까지는 문제 없다. 하지만 만약 무기의 개수가 10개로 늘어난다면? 50개, 100개로 늘어나버린다면? 하나하나 선언하기도 귀찮을뿐더러 프로그래머가 상수를 선언하는 과정에서 실수를 저지를 확률이 높아진다. 만약 위 예제에서 STAFF와 AXE가 동일한 2값을 가지게 된다면? 마법사 캐릭터가 지팡이를 골랐음에도 도끼를 가지고 싸워야하는 엉뚱한 일이 일어날지도 모른다. 

 

때문에 열거 형식은 같은 범주에 속하는 여러개의 상수를 선언할때 사용된다. 이제 실행결과를 한 번 살펴보도록 하자.

 

 

<실행결과>

 

 

요소의 이름만 넣어주었음에도 알아서 정수 데이터 값을 가지고 있다. 이것은 컴파일러가 자동으로 값을 할당해준 것이다. 아무런 값도 지정하지 않았을 경우, 첫 번째 요소는 0, 두 번째 요소는 1, 세 번째 요소는 2··· 이런식으로 순서에 따라 +1의 값을 채워준다. 물론 값을 직접 채워주는 것도 가능하다. 예시를 살펴보자.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Program
    {
        enum Weapon { SWORD=10, STAFF, GUN, AXE=50, BOW };

        static void Main(string[] args)
        {
            Console.WriteLine((int)Weapon.SWORD);
            Console.WriteLine((int)Weapon.STAFF);
            Console.WriteLine((int)Weapon.GUN);
            Console.WriteLine((int)Weapon.AXE);
            Console.WriteLine((int)Weapon.BOW);
        }
    }
}

 

 

<실행 결과>

 

 

 

SWORD와 AXE에만 값을 넣었더니 위와 같은 결과가 나타났다. 값을 할당하지 않은 요소에는 역시 컴파일러가 자동으로 값을 넣어주는데 그 값은 이전 요소로부터 1씩 더한 값이다.

 

 

여기서 하나 더, 우리는 열거 형식을 사용해 변수를 만들 수 있다. 이게 무슨 말이냐? 우리는 앞서 enum Weapon이라는 열거형식을 만들어냈다. 이 말은 즉 Weapon은 변수가 아닌 '열거 형식' 이라는 새로운 형식이라는 것이다. 우리는 열거 형식을 통해 변수를 선언하고 그 안에 열거 형식이 가지고 있는 요소들을 대입할 수 있다. 

 

Weapon select=Weapon.SWORD;

 

바로 이렇게!

물론 Weapon으로 선언된 변수는 Weapon 형식의 데이터만 담을 수 있다. 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Program
    {
        enum Weapon { SWORD, STAFF, GUN, AXE, BOW };

        static void Main(string[] args)
        {
            Weapon select = Weapon.SWORD;

            Console.WriteLine(select==Weapon.SWORD);
            Console.WriteLine(select==Weapon.STAFF);
            Console.WriteLine(select==Weapon.GUN);

        }
    }
}

 

 

<실행 결과>

 

 

select 변수에 Weapon.SWORD의 값이 무사히 대입된 모습이다.

 

 

 

 

2. Nullable 형식

 

C# 컴파일러는 변수를 선언하면 그 안에 반드시 값을 넣도록 강제한다. 하지만 때때로 프로그래밍을 하다보면 어떠한 값도 가지지 않는 변수가 필요할 때가 있다. (게임에서 플레이어의 인벤토리를 예시로 들 수 있는데 주인공이 아무런 아이템도 습득하지 못했다면 인벤토리는 텅 비어있게 된다.) 이럴 때 사용하는 것이 바로 Nullable형식이다. Nullable형식은 변수가 0이 아닌 완전히 비어있는 null값을 가질 수 있도록 만들어준다. (0과 Null은 다른 개념이다! 변수에 0을 할당할 경우 0이라는 값 그 자체가 할당된 것이지 비어있는 상태인 것은 아니다.)

 

<Nullable 형식 선언>

데이터형식? 변수이름;
int? a=null;
float? b=null;
double c?=null;

* Nullable형식은 값형식에서만 사용 가능하다.

 

 

Nullable형식은 HasValue와 Value라는 두 가지 속성을 가지고 있다. HasValue는 해당 변수가 값을 가지고 있는지를 판단하고 Value는 변수에 담겨있는 값을 나타낸다. 만약 Nullable 형식 변수의 HasValue가 False값을 가지고 있다면 그 변수는 비어있다(null)라는 뜻이다.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Program
    {
        enum Weapon { SWORD, STAFF, GUN, AXE, BOW };

        static void Main(string[] args)
        {
            int? inv = null;
            Console.WriteLine(inv.HasValue);

            Weapon select = Weapon.SWORD;

            inv = (int)select;
            Console.WriteLine(inv.HasValue);
            Console.WriteLine(inv.Value);

        }
    }
}

 

<실행 결과>

 

 

 

3. var 형식

 

우선 예시코드를 먼저 살펴보자.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_ConstEnumNullableVar
{
    class Var
    {
        static void Main(string[] args)
        {
            var a = 1;
            var b = 1.5;
            var c = "Hello";

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
        }
    }
}

 

 

변수 a, b, c를 모두 var 형식으로 선언했다. 그리고 변수에 할당된 값은 각각 정수, 소수, 그리고 문자열이다. 

정수와 소수, 문자열을 int, float(또는 double), string으로 선언하지 않았는데 괜찮은 것일까? 한 번 실행결과를 확인해보자.

 

 

 

 

 

에러 메세지 없이 무사히 실행되었다. var을 사용해 변수를 선언하면 컴파일러가 자동으로 해당 변수의 형식을 지정해준다. 때문에 var은 반드시 선언과 동시에 초기화를 해주어야 한다. 초기화를 해주지 않으면 컴파일러가 데이터의 형식을 추측할 수 없기 때문이다. 아무리 똑똑한 컴퓨터라도 있지도 않은 값의 형식을 알아낼 수는 없으니 말이다.  

 

 

데이터의 형식에 상관없이 사용할 수 있다는 점에서 var 형식은 참조형식의 자료형인 object와 비슷하다. 하지만 object 형식은 컴파일러가 데이터의 값을 보고 추측하여 데이터 형식을 지정해주는 것이 아닌 object 형식 그대로 메모리 공간이 생긴다. object a=10; 이라는 변수가 있다면 10을 힙에 넣어놓고 a가 10의 주소를 가리키게 해놓을 것이다. 반면 var 형식은 프로그램이 실행되면 var형식으로 a를 int형식으로 바꾸어준다.