Quick Reference
변수는 Type name = value; 또는 선언 뒤 대입으로 만듭니다. 지역 변수는 initializer가 있을 때 var로 정적 타입을 추론할 수 있고, numeric literal은 suffix·prefix에 따라 type이 달라집니다.
int count = 3;
string name = "Mina";
bool ready = true;
char grade = 'A';
long distance = 384_400_000L;
float gravity = 9.81f;
decimal price = 19.99m;
int hex = 0x2A;
int binary = 0b_0010_1010;
var labels = new List<string>(); // List<string>로 고정- 일반 정수는
int, 큰 정수는long, 포인터 크기와 맞춰야 하는 interop은nint/nuint를 검토합니다. - 일반 실수 계산은
double, 저장량이 중요한 대규모floatdata, 10진 자릿수 기준 금액은decimal이 보통의 출발점입니다. var는 runtime dynamic typing이 아니며 initializer가 필수인 local variable 문법입니다.decimal도 유한한 자릿수이므로 세금·통화의 반올림 규칙을 별도로 정해야 합니다.
선언과 literal
int deferred;
deferred = 10;
const int MaxRetries = 3;
string? optionalName = null;
object value = default(string) ?? "fallback";numeric literal은 decimal, hexadecimal 0x, binary 0b, digit separator _를 쓸 수 있습니다. suffix가 없으면 정수 literal은 값에 따라 int, uint, long, ulong 중 하나가 되고, 소수점 literal은 double입니다. L, U, UL, F, M suffix로 의도를 명시합니다.
int dec = 42;
int hex = 0x2A;
int bin = 0b_0010_1010;
long large = 1_000_000_000L;
uint flags = 0xFF_FFU;
double ratio = 1.5e6;
float small = 3.14f;
decimal money = 3.14m;문자는 single quote, 문자열은 double quote를 씁니다. 문자열의 escape가 많으면 raw string literal(""") 또는 verbatim string(@"...")을, 값을 넣으면 interpolation($"...")을 사용합니다.
숫자 타입과 선택
| 종류 | 주로 쓰는 type | 핵심 경계 |
|---|---|---|
| 일반 정수·index·count | int | 범위를 넘으면 long 또는 validation |
| 큰 정수 ID·byte count | long | API·database 범위와 signedness 확인 |
| byte/bit flag/interop | byte, ushort, uint, ulong | .NET API의 signed type 관례와 변환 확인 |
| native interop size | nint, nuint | 32/64-bit platform에 따라 크기 변화 |
| 일반 부동소수 계산 | double | IEEE 754 rounding, NaN, infinity |
| 대규모 graphics/ML data | float | 약 6-9 유효 자릿수 |
| 금액·10진 자릿수 기준 계산 | decimal | 28-29 자릿수, 도메인 반올림 정책 필요 |
float/double은 binary floating point라 0.1 같은 10진수를 정확히 표현하지 못할 수 있습니다. decimal은 10진 자릿수를 더 정확히 표현하지만 결과가 무한 자릿수이거나 범위를 넘으면 여전히 반올림·예외 정책이 필요합니다. 금액은 type 선택 뒤에도 통화·세율·rounding mode를 domain rule로 정합니다.
var, dynamic, 변환
var numbers = new List<int>(); // compile-time: List<int>
// var later; // 초기화가 없어 불가
// var unknown = null; // null만으로 type 추론 불가
dynamic lateBound = "Mina"; // member binding을 runtime에 수행
Console.WriteLine(lateBound.Length);var는 field, parameter, return type에 쓸 수 없고 local variable의 compiler type inference입니다. dynamic은 compile-time member 검사를 늦춰 runtime binder exception이 날 수 있으므로 COM, dynamic JSON 등 필요한 interop boundary에 한정합니다.
numeric conversion은 compiler가 허용하는 것과 값 손실이 없다는 보장이 다릅니다. 예를 들어 long에서 float로의 implicit conversion은 허용되지만 precision을 잃을 수 있습니다. narrowing conversion은 explicit cast가 필요하며, overflow 결과는 checked/unchecked context에 따라 달라집니다.
long source = 9_007_199_254_740_993L;
float approximate = source; // 허용되지만 정확한 값 보장 없음
double pi = 3.14;
int truncated = checked((int)pi); // 3, integral conversion은 zero 방향 절삭문자열 input의 형식 실패는 cast로 해결하지 않습니다. 사용자·network 입력은 TryParse와 culture/format policy를 사용하며, 자세한 경계는 Parse와 TryParse에서 확인합니다.
자주 틀리는 부분
bool을 "1 bit 변수"로, decimal을 "모든 금액 계산이 자동으로 정확"하다고 설명하지 않습니다. source type의 언어 크기, runtime storage, business rounding rule은 서로 다른 문제입니다.
var가 편하다는 이유로 right-hand side가 모호한 numeric literal까지 모두 숨기지 마세요. var timeout = 30보다 시간 단위와 type이 드러나는 이름·type이 API 실수를 줄일 때가 많습니다.
참고 링크
2 sources