C#은 많은 정적 타입 언어가 그렇듯 정수를 나타내는 여러 타입을 제공하며, 각 타입마다 고유한 값의 범위를 가져요. 범위의 아래쪽 끝을 보면 sbyte 타입은 최솟값이 -128이고 최댓값이 127이에요. 모든 정수 타입과 마찬가지로 이 값들은 <type>.MinValue와 <type>.MaxValue로 사용할 수 있어요. 범위의 위쪽 끝을 보면 long 타입은 최솟값이 -9,223,372,036,854,775,808이고 최댓값이 9,223,372,036,854,775,807이에요. 그 사이에는 short와 int 타입이 있어요.
위의 각 타입에는 부호 없는 대응 타입이 있어요: sbyte/byte, short/ushort, int/uint, long/ulong이에요. 모든 경우에 값의 범위는 0부터 부호 있는 타입의 음수 최댓값에 2를 곱하고 1을 더한 값까지예요.
부호 없는 정수 타입의 값은 단순한 2진 표현으로 나타내요. 부호 있는 타입의 값은 2의 보수 부호 있는 수 표현을 사용해요.
정수 타입이 이렇게 많은 것은 레지스터의 크기, CPU 명령어 인자의 크기, CPU에서 부호를 처리하는 방식 같은 기계 아키텍처를 반영하기 때문이에요. long 타입의 값은 64비트를 사용하는 반면, sbyte 타입의 값은 8비트를 사용해요. 어떤 경우에는 CPU 성능, 메모리 사용량, 심지어 디스크 사용량에도 영향을 미칠 수 있어요(일반적으로 더 작은 정수 타입을 선택하는 것이 유리해요). 정수 type을 선택하는 것은 다른 개발자에게 값의 예상 범위에 대한 정보를 전달하는 간단한 방법이 되기도 해요. int 타입은 특별한 점이 없는 사용처에서 기본 타입으로 널리 사용돼요. long이나 ulong은 단순한 식별자로 널리 사용돼요. 타입의 크기(바이트)가 값의 범위를 결정해요.
지금까지 다룬 타입들은 원시 타입이에요. 각 타입에는 struct 별칭이 짝을 이뤄요. 이 별칭은 타입과 연결된 필드(예: MinValue)와 메서드(예: ToString())를 구현해요.
| 타입 | 구조체 | 너비 | 최솟값 | 최댓값 |
|---|---|---|---|---|
sbyte |
SByte |
8 bit | -128 | +127 |
short |
Int16 |
16 bit | -32_768 | +32_767 |
int |
Int32 |
32 bit | -2_147_483_648 | +2_147_483_647 |
long |
Int64 |
64 bit | -9_223_372_036_854_775_808 | +9_223_372_036_854_775_807 |
byte |
Byte |
8 bit | 0 | +255 |
ushort |
UInt16 |
16 bit | 0 | +65_535 |
uint |
UInt32 |
32 bit | 0 | +4_294_967_295 |
ulong |
UInt64 |
64 bit | 0 | +18_446_744_073_709_551_615 |
한 타입의 변수(또는 식)는 다른 타입으로 쉽게 변환할 수 있어요. 예를 들어 대입 연산에서 대입되는 값(rhs)의 타입이 그 값이 대입 대상(lhs) 타입의 범위 안에 들어감을 보장한다면, 단순한 대입만 하면 돼요:
ulong ul;
uint ui = uint.MaxValue;
ul = ui; // no problem
반면 대입하는 쪽 타입의 범위가 대입 대상의 값 범위의 부분집합이 아니라면, 특정 값이 대입 대상의 범위 안에 있더라도 () 캐스팅 연산이 필요해요:
uint ui;
short s = 42;
ui = (uint)s;
위 예에서 값이 대입 대상의 범위를 벗어난다면 오버플로가 발생해요. overflow를 참고해요.
캐스팅이 필요한지는 특정 값이 아니라 관련된 두 타입에 의해 결정돼요.
다음 단락에서는 정수 타입의 캐스팅을 다뤄요. (casting)에서는 캐스팅과 타입 변환을 더 폭넓게 다뤄요. 정수 타입과 실수, char, bool 사이의 변환에 대해서는 그 문서를 참고해요.
C#의 타입 시스템은 _C_나 JavaScript의 것보다 다소 엄격해서, 그 결과 캐스팅 연산이 더 제한적이에요. 암시적 캐스팅은 "to" 타입이 "from" 타입 값의 크기와 부호를 보존할 수 있는 한 두 숫자 타입 사이에서 일어나요.
암시적 캐스팅은 특별한 문법으로 표시하지 않아요.
숫자 타입을 암시적으로 캐스팅할 수 없을 때는 일반적으로 명시적 캐스팅 연산자를 사용할 수 있어요.
캐스팅되는 값을 "to" 타입이 나타낼 수 없을 때, 즉 타입이 충분히 넓지 않거나 부호 충돌이 있을 때는 오버플로 예외가 발생할 수 있어요.
int largeInt = Int32.MaxValue;
int largeNegInt = Int32.MinValue;
ushort shortUnsignedInt = ushort.MaxValue;
// implicit cast
int from_ushort = shortUnsignedInt; // 65535
float from_int = largeInt; // -21474836E+09
// explicit cast
uint from_largeInt = (uint)largeInt; // 2147483647
uint from_neg = (uint) largeNegInt; // 2147483648 or OverflowException is thrown (if checked)
BitConverter 클래스는 정수 타입을 바이트 배열로, 또는 그 반대로 변환하는 편리한 방법을 제공해요.