빠른 비교
// Parse — 실패 시 예외 발생
int count = int.Parse("42");
// TryParse — 실패 시 false 반환
if (int.TryParse(userInput, out int value))
Process(value);
else
ShowError("숫자를 입력하세요");
// 무시 패턴 — 성공 여부만 확인
bool isNumber = int.TryParse(text, out _);갈리는 기준
어떤 파싱 형태가 있나
파싱 카드는 아래 세 가지를 먼저 구분하면 됩니다.
int value = int.Parse("42"); // 실패 시 예외
bool ok = int.TryParse(text, out int result); // 실패 시 false
double.TryParse("3.14", NumberStyles.Float,
CultureInfo.InvariantCulture, out double pi); // 형식 제어- 형식이 보장되면
Parse - 실패가 흔하면
TryParse - 로케일이 섞이면
NumberStyles+CultureInfo
Parse vs TryParse — 예외 비용의 차이
Parse는 실패 시 FormatException 을 던집니다. 예외 생성은 stack trace를 캡처하는 비용이 있어 빈번한 실패 경로에서는 비효율적입니다. TryParse는 예외 없이 bool로 성공/실패를 반환합니다.
// Parse가 내부에서 하는 일 (개념)
int Parse(string s)
{
if (!TryParse(s, out int result))
throw new FormatException($"'{s}'은 올바른 int 형식이 아닙니다");
return result;
}
// 사용자 입력 1000번 중 100번이 실패한다면 — TryParse가 올바른 선택
// 설정 파일처럼 형식이 보장된다면 — Parse도 적합다양한 타입의 파싱
파싱 패턴은 int에만 있지 않습니다. 대부분의 기본 타입이 동일한 패턴을 제공합니다.
// 정수
int.TryParse("42", out int n);
long.TryParse("9999999999", out long l);
// 실수
double.TryParse("3.14", out double d);
decimal.TryParse("9.99", out decimal m);
// 날짜/시간
DateTime.TryParse("2026-03-25", out DateTime dt);
DateOnly.TryParse("2026-03-25", out DateOnly date);
// GUID
Guid.TryParse("550e8400-e29b-41d4-a716-...", out Guid g);
// Enum
Enum.TryParse<DayOfWeek>("Monday", out DayOfWeek day);
// bool
bool.TryParse("true", out bool flag);// ❌ 사용자 입력에 Parse 남용
int age = int.Parse(userInput);
// ✅ 입력 경계에서는 TryParse가 기본
if (!int.TryParse(userInput, out int parsedAge))
return Results.BadRequest("숫자를 입력하세요.");NumberStyles와 CultureInfo — 형식 제어
숫자 문자열에 통화 기호, 천 단위 구분자, 소수점 기호가 섞여 있을 때 NumberStyles 와 CultureInfo 로 파싱 방식을 제어합니다.
// 쉼표가 있는 숫자
int.TryParse("1,234", NumberStyles.AllowThousands,
CultureInfo.InvariantCulture, out int n); // n = 1234
// 통화 기호 포함
decimal.TryParse("$9.99", NumberStyles.Currency,
CultureInfo.GetCultureInfo("en-US"), out decimal price);
// 한국어 로케일 (소수점 구분자 차이 없음)
double.TryParse("3.14", NumberStyles.Float,
CultureInfo.InvariantCulture, out double pi);CultureInfo.InvariantCulture 는 로케일에 무관한 고정된 파싱 규칙을 사용합니다. 서버 간 데이터 교환이나 파일 파싱에서는 이것을 명시하는 편이 안전합니다.
Span 기반 파싱 — allocation 없음
.NET 5+에서는 ReadOnlySpan<char> 를 받는 TryParse 오버로드가 추가됐습니다. 큰 문자열에서 일부를 파싱할 때 Substring() 없이 처리할 수 있습니다.
string line = "score=1234,level=5";
ReadOnlySpan<char> span = line.AsSpan(6, 4); // "1234"
int.TryParse(span, out int score); // ✅ 새 string 할당 없음선택 기준
| 항목 | Parse | TryParse |
|---|---|---|
| 실패 처리 | 예외 발생 | false 반환 |
| 적합한 경우 | 신뢰된 형식, 실패가 예외 상황 | 사용자 입력, 실패가 예상 경우 |
| 결과 반환 | 반환값 | out 매개변수 |
| 성능 | 실패 시 비용 큼 | 항상 저비용 |
주의할 점
Parse를 사용자 입력에 남용하면 사용자가 형식을 잘못 입력할 때마다 예외가 발생합니다. 예외는 "정말 예외적인 상황"을 표현할 때 더 가치가 큽니다. 실패가 자주 예상되는 곳에서는 TryParse를 기본으로 선택하세요.
소수점 구분자(. vs ,)는 로케일마다 다릅니다. 로케일을 명시하지 않으면 실행 환경에 따라 파싱 결과가 달라질 수 있습니다. 서버 코드에서는 CultureInfo.InvariantCulture를 명시하는 습관을 들이세요.
참고 링크
2 sources