[C#] 공용 형식 시스템.


C#은 다양한 종류의 데이터를 다룰수 있다.

byte, int, float, string, object와 같은 다양한 기본데이터 형식을 제공하며,

프로그래머가 이들을 조합해여 복잡한 데이터 형식을 만들어 사용할 수 있다.


또한, C#에서는 스택과 힙이라는 두 가지 메모리 영역을 활용함으로써 변수의 생명주기에 따라 변수를

값 형식이나 참조형식으로 만들어 사용할 수 있다.


이 모든 데이터 형식 체계는 사실 C#의 고유의 것이 아니다.

공용 형식 시스템(Common Type System)이라고 하는 .NET 프레임워크의 형식 체계의 표준을 그대로

따르고 있을 뿐이다.


공용 형식 시스템의 뜻을 풀어보자면 "모두가 함께 사용하는 데이터 형식 체계" 라고 할 수 있다.

C#을 비롯한 .NET 프레임워크를 지원하는 모든언어를 뜻한다.


마이크로소프트가 이러한 시스템을 도입한 이유는 .NET 언어들끼리 호환성을 갖도록 하기 위해서이다.



C#과 C++의 기본 데이터 형식을 살펴 보도록 하자.


클래스 이름 

C# 형식 

 C++ 형식

 비주얼 베이직 형식 

 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.Boolean

 bool bool Boolean
 System.Char char wchar_t Char
 System..Decimal decimal Decimal Decimal
 System.IntPtr

 없음

 없음

 없음

 System.UIntPtr

 없음 없음 없음
 System.Object object Object*

 Object

 System..String string String* String




공용 형식 시스템의 형식은 각 언어에서 코드에 그대로 사용할수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
 
namespace CTS
{
    class MainApp
    {
        static void Main(string[] args)
        {
            System.Int32 a = 123;
            int b = 456;
 
            Console.WriteLine("a type:{0}, value:{1}", a.GetType().ToString(), a);
            Console.WriteLine("b type:{0}, value:{1}", b.GetType().ToString(), b);
            
            System.String c = "abc";
            string d = "def";
 
            Console.WriteLine("c type:{0}, value:{1}", c.GetType().ToString(), c);
            Console.WriteLine("d type:{0}, value:{1}", d.GetType().ToString(), d);
 
            // 결과
            // a type: System.Int32, value: 123
            // b type: System.Int32, value: 456
            // c type: System.String, value: abc
            // d type: System.String, value: def
        }
    }
}
cs




※ GetType() 메소드 ToString() 메소드


모든 데이터 형식은 object 형식으로부터 상속받는다고 말한적이 있을것이다.

GetType()와 ToString()메소드는

System.Int32와 int, System.String과 string 형식이

object형식으로부터 물려받아 갖고 있는 것이다.


[C#] var형식


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

하지만, 약한 형식 검사를 지원해주기도 한다. 바로 var라는 키워드 이다.


강력한 형식검사 

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

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


약한 형식검사(var)

- 자동으로 해당 변수의 형식을 지정해준다.

- int, long, unit, ulong 같은 형식을 외울 필요가 없다.

- 변수의 선언과 동시에 초기화 해야한다.

- 지역 변수로만 사용할 수 있다.



var키워드를 사용해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
 
namespace UsingVar
{
    class MainApp
    {
        static void Main(string[] args)
        {
            var a = 20;
            Console.WriteLine("Type {0}, Value {1}", a.GetType(), a);
            // 결과 : Type: System.Int32, Value: 20
 
            var b = 3.14;
            Console.WriteLine("Type {0}, Value {1}", b.GetType(), b);
            // 결과 : Type: System.Double, Value: 3.14
 
            var c = "헬로우 월드?";
            Console.WriteLine("Type {0}, Value {1}", c.GetType(), c);
            // 결과 : Type: System.String, Value: 헬로우 월드?
        }
    }
}
cs



배열도 사용 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
 
namespace UsingVar
{
    class MainApp
    {
        static void Main(string[] args)
        {
            var a = new int[] {10,20,30};
            Console.WriteLine("Type {0}, Value: ", a.GetType());
            
            foreach(var e in a)
                Console.Write("{0} ", e)
            Console.WriteLine();
 
            // 결과 : Type: System.Int32[], Value: 10 20 30
        }
    }
}
cs




var형식과 object형식


위의 예제코드를 object형식으로도 작성이 가능하다.

그럼 var와 object는 같은거 아닌가? 라고 생각할수도 있지만.


아니다.


object a = 20;

이라는 코드가 있다고 하자.

컴파일이 실행되면 20은 박싱되어 힙에 들어가고 a는 힙을 가르키게 된다.


var a = 20;은 컴파일러가 a의 형식을 파악한다. 

int a = 20;으로 바꿔 컴파일 시킨다.

컴파일이 실행되면 a를 스택에 올려놓게 된다.


두 개의 형식은 명확히 다른거라고 알아두자.


[C#] Object형식, 박싱과 언박싱.


1. Object형식


object형식은 "상속" 덕분에 어떤 데이터든지 다룰수 있는 데이터 형식이다.


C#은 object가 모든 데이터를 다룰 수 있도록 하기 위해 특별 조치를 취했는데,

모든 데이터 형식이 자동으로 object형식으로부터 상속받게 한 것이다.

다시 말해 object형식이 모든 데이터 형식의 부모라고 하면 된다.


※ 모든 데이터 형식이 가능하다. 프로그래머가 만든 데이터 형식도 마찬가지다.



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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System
 
namespace Object
{
    class Test
    {
        static void Main(string[] args)
        {
            object a = 100;
            object b = 3.14;
            object c = true;
            object d = "헬로우 월드";
            
            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(d);
        }
    }
}
cs



각 자료형이 처리하는 방식이 다른데 어떻게 이런일이 가능할까?

우리는 그걸 알기 위해 이 뒤에 일어나는 메커니즘을 이해할 필요가 있다.

그 메커니즘을 박싱, 언박싱 이라고 한다.




2. 박싱과 언박싱


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

int나 double 형식은 값 형식이기 때문에 스택에 할당한다.


그런데 앞에서 값 형식의 데이터를 object형식 객체에 담았다.

이 경우는 어느 메모리에 데이터가 할당될까?


object형식은 값 형식의 데이터를 힙에 할당하기 위한 박싱(Boxing)기능을 제공한다.


object형식에 값 형식의 데이터를 할당하려는 시도가 이루어지면 object형식은 박싱을 수행해서 해당 데이터를 힙에 할당한다.


이렇게 박싱이 일어나는 한 편, 힙에 있던 값 형식 데이터를 값 형식 객체에 다시 할당해야 하는 경우가 있다.

다음이 그런 경우다.


1
2
object a = 20;
int b = (int)a;
cs

위 코드에서 a는 20이 박싱되어 저장되어 있는 힙을 참조하고 있다.

b는 a가 참조하고 있는 메모리로부터 값을 복사하려고 하는 중이다.

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



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
 
namespace BoxingUnBoxing
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int a = 123;
            object b = (object)a;        // a에 담긴 값을 박싱하여 힙에 저장
            int c = (int)b;              // b에 담긴 값은 언박싱하여 스택에 저장
            
            Console.WriteLine(a);        // 결과 : 123
            Console.WriteLine(b);        // 결과 : 123
            Console.WriteLine(c);        // 결과 : 123
        }
    }
}
cs



prev 1 ··· 12 13 14 15 16 17 18 ··· 29 next