[C#] 2.1 데이터에 관한 문법 사항

C#에서는 프로그램 내에 관리할 데이터를 표현하기 위한 문법 사항으로 형식과 변수를 제공하고 있습니다. 형식이란 프로그램 내에 표현할 데이터 종류에 대한 약속입니다. 이러한 형식은 변수 선언이나 개체 생성을 통해 구체화합니다. 이처럼 구체화 된 데이터에 접근하기 위해서 변수를 사용하게 됩니다.

C# 형식.NET Framework형식설명 및 표현 범위
boolSystem.Boolean논리 값을 표현 (true 혹은 false)
byteSystem.Byte부호 있는 8비트 정수(-128~127)
sbyteSystem.SByte부호 없는 8비트 정수(0~255)
charSystem.Char유니코드 16비트 문자
decimalSystem.Decimal128비트 데이터 형식
doubleSystem.Double7개의 자릿수를 갖는 실수 (근사치)
floatSystem.Single15~16개의 자릿수를 갖는 실수(근사치)
intSystem.Int32부호 있는 32비트 정수
uintSystem.UInt32부호 없는 32비트 정수
longSystem.Int64부호 있는 64비트 정수
ulongSystem.UInt64부호 없는 64비트 정수
objectSystem.Object모든 형식의 기반 형식
shortSystem.Int16부호 있는 16비트 정수
ushortSystem.UInt16부호 없는 16비트 정수
stringSystem.String0개 이상의 유니코드 문자로 구성된 시퀀스

C#에서의 형식은 이미 정의되어 제공되는 기본 형식과 필요할 때 개발자가 정의해서 사용하는 사용자 정의 형식으로 나눌 수 있습니다. 그리고 형식은 구체화 된 데이터에 접근하기 위한 변수가 값을 의미하거나 생성된 개체를 참조하는가에 따라 값 형식과 참조 형식으로 나누기도 합니다. 기본 형식에는 참과 거짓을 표현할 수 있는 bool 형식과 유니코드 문자를 표현하기 위한 char 형식, 정수와 실수를 표현하기 위한 여러 형식과 문자열을 위해 string과 모든 형식의 기반 형식인 object를 제공하고 있습니다. 기본 형식으로 제공되는 형식 중에 string과 object는 참조 형식이며 나머지 형식들은 모두 값 형식입니다.

C#에서는 기본 형식 외에 필요한 형식을 정의하여 사용할 수 있게 사용자 정의 형식을 제공하고 있습니다. 사용자 정의 형식은 표현할 수 있는 값의 종류를 정의하는 열거형과 여러 가지 멤버들을 하나의 형식 내에 정의할 수 있는 구조체와 클래스 등이 있습니다. 이 중에 구조체와 열거형은 값 형식이며 클래스는 참조 형식입니다.

C#에서 값 형식들은 변수들이 독립적으로 사용됩니다. 이에 반해 참조 형식은 변수들이 관리화 힙에 할당된 개체를 참조하여 사용되기 때문에 하나의 개체를 사용하는 여러 개의 변수가 있을 수 있습니다.

C#에서 값 형식의 변수는 독립적으로 사용되므로 같은 형식의 변수로 초기화되거나 대입 연산 등이 이루어질 때 단순히 값을 복사할 뿐입니다. 즉, 값 형식에서 변수가 다르다는 것은 할당된 메모리가 다르다는 것을 의미합니다. 참조 형식은 변수는 단순히 개체를 참조하여 사용되는 이름이기 때문에 같은 개체를 참조하는 여러 개의 변수가 있을 수 있습니다.

값 vs 참조
[그림 8] 값 vs 참조

다음의 예제 코드는 값 형식과 참조 형식의 차이에 대한 이해를 돕기 위한 간단한 코드입니다.

▶ Ex-Value VS Reference

using System;
namespace ValueVSReference
{
    class MyInt // 사용자 정의 클래스 - 참조 형식
    {
        public int Value{    get;    set;    } //속성
        public MyInt(int value) //생성자
        {
            Value = value; 
        }
        public override string ToString() //재정의
        {
            return Value.ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //값 형식에 대한 테스트 코드
            int i = 1; //값 형식 변수 i 선언 및 초기화
            int j = i; //값 형식 변수 j 선언 및 초기화(i를 초기화에 사용)

            i++;  //i를 1 증가
            Console.WriteLine("i:{0} j:{1}",i,j); //값 형식인 i와 j값을 출력

            //참조 형식에 대한 테스트 코드
            MyInt a = new MyInt(1); // MyInt 개체를 생성하여 변수 a에 대입
            MyInt b = a; //MyInt 형식 변수 b 선언 및 초기화(a를 초기화에 사용)

            a.Value++; //a의 속성 Value를 1 증가
            Console.WriteLine("a:{0} b:{1}", a, b); //참조 형식인 a와 b를 출력
        }
    }
}

먼저, 값 형식인 int 형식 변수 i를 선언하며 1로 초기화를 하였습니다. 그리고 int 형식 변수 j를 선언하면서 i로 초기화를 하였습니다. 이 경우에 i와 j는 값으로 1을 가지고 있으며 두 개의 변수는 독립적으로 정수 값을 관리합니다. 만약, i의 값을 증가시킨다고 하면 i는 2가 되지만 j는 아무런 영향도 받지 않습니다.

참조 형식을 위해 MyInt 이름의 클래스를 하나 정의하였습니다. MyInt에는 int 형식의 멤버 속성 Value를 갖도록 정의하였습니다. 그리고 MyInt 형식 변수 a를 선언하면서 1값을 입력 인자로 MyInt 개체를 생성하여 초기화하였습니다. 또한, MyInt 형식 변수 b를 선언하면서 a로 초기화를 하였죠. 이 경우에 변수 a와 변수 b는 같은 개체를 참조하게 됩니다. 만약, a의 멤버 속성 Value값을 증가하면 변수 b도 같은 개체를 참조하므로 출력 결과도 당연히 같습니다.

▶ Ex-ValueVSReference 실행 결과

i:2  j:1
a:2 b:2