Как в C# проверить, является ли строка числом? (IsNumeric аналог)
string userInput = "123.45";
try
{
int number = Convert.ToInt32(userInput);
Console.WriteLine("Это целое число");
}
catch (FormatException)
{
// Пытаюсь проверить на double
try
{
double doubleNumber = Convert.ToDouble(userInput);
Console.WriteLine("Это число с плавающей точкой");
}
catch (FormatException)
{
Console.WriteLine("Это не число!");
}
}
Этот код работает, но он ужасно выглядит: два вложенных try-catch. Плюс, если строка пустая или содержит только пробелы, он тоже выкинет исключение. Подскажите, как сделать это правильно и красиво? Может быть, есть какой-то метод наподобие string.IsNumber()?
Спасибо!
<<Лучший способ: TryParse вместо Try-Catch
Вы абсолютно правы: использовать исключения для проверки формата — это антипаттерн в C#. Исключения созданы для исключительных ситуаций, а не для обычной валидации. Встроенный и самый производительный способ — это метод TryParse, который есть у всех числовых типов (int, double, decimal и т.д.). Он возвращает bool и не выбрасывает исключений.
Решение для целых чисел
string input = "123";
if (int.TryParse(input, out int result))
{
Console.WriteLine($"Это целое число: {result}");
}
else
{
Console.WriteLine("Это не целое число");
}
Решение для чисел с плавающей точкой (с учётом культуры)
Важно: double.TryParse по умолчанию использует текущую культуру потока. В русской локали разделитель целой и дробной части — запятая (","), а в американской — точка ("."). Чтобы избежать сюрпризов, всегда указывайте NumberStyles и CultureInfo:
using System.Globalization;
string input = "123.45";
NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands;
CultureInfo culture = CultureInfo.InvariantCulture;
if (double.TryParse(input, style, culture, out double result))
{
Console.WriteLine($"Это число с плавающей точкой: {result}");
}
else
{
Console.WriteLine("Это не число");
}
Универсальная функция (IsNumeric аналог)
Если вам нужно определить, является ли строка любым числом (целым или дробным), можно написать такой метод:
public static bool IsNumeric(string input)
{
if (string.IsNullOrWhiteSpace(input))
return false;
// Пробуем распарсить как double (с плавающей точкой)
NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands;
CultureInfo culture = CultureInfo.InvariantCulture;
return double.TryParse(input, style, culture, out _);
}
Использование:
Console.WriteLine(IsNumeric("123")); // True
Console.WriteLine(IsNumeric("123.45")); // True
Console.WriteLine(IsNumeric("-0.001")); // True
Console.WriteLine(IsNumeric("1e5")); // True (научная нотация)
Console.WriteLine(IsNumeric("abc")); // False
Console.WriteLine(IsNumeric("")); // False
Что ещё нужно знать?
- decimal.TryParse — используйте для финансовых расчётов (нет проблем с округлением).
- int.TryParse — только целые числа в диапазоне
int(от -2,147,483,648 до 2,147,483,647). - long.TryParse — для больших целых чисел.
- Метод
TryParseне поддерживает шестнадцатеричные числа (например "0xFF") — для этого нуженNumberStyles.HexNumber. - Проверка на
string.IsNullOrWhiteSpaceобязательна, иначеTryParseвернётfalseдля пустой строки, но лучше отсечь такие случаи сразу.
Почему это лучше, чем try-catch?
- Производительность: Исключения — дорогая операция (создание объекта, раскрутка стека).
TryParseработает в десятки раз быстрее при большом количестве невалидных строк. - Читаемость: Код становится плоским и понятным.
- Предсказуемость: Вы сами контролируете логику, не полагаясь на механизм исключений.
Таким образом, забудьте про Convert.ToInt32 с try-catch для валидации. Используйте TryParse — это идиоматичный и правильный путь в C#.
Альтернативный подход: Регулярные выражения
Если вам нужно проверить, что строка соответствует строго определённому формату числа (например, только целые положительные числа без ведущих нулей), можно использовать регулярные выражения. Это даёт больше гибкости, но работает медленнее, чем TryParse.
using System.Text.RegularExpressions;
public static bool IsInteger(string input)
{
if (string.IsNullOrWhiteSpace(input))
return false;
// Только целые числа, опционально со знаком минус
string pattern = @"^-?\d+$";
return Regex.IsMatch(input, pattern);
}
public static bool IsDecimal(string input)
{
if (string.IsNullOrWhiteSpace(input))
return false;
// Целая часть + опционально точка и дробная часть
string pattern = @"^-?\d+(\.\d+)?$";
return Regex.IsMatch(input, pattern);
}
Когда это может пригодиться?
- Валидация телефонных номеров или кодов, где нужна строгая маска.
- Проверка на Scientific Notation (например, "1.5e-3") — регулярное выражение будет сложнее, но возможно.
- Отсечение лишних символов (пробелы, знаки валют).
Недостатки
- Производительность: Регулярные выражения медленнее
TryParse, особенно при большом количестве вызовов. - Сложность: Нужно быть осторожным с граничными случаями (например, пустая строка, только точка, ведущие нули).
- Локализация: Регулярные выражения не учитывают культуру (запятая vs точка).
Поэтому для 95% случаев используйте TryParse. Регулярные выражения оставьте для специфических форматов, которые не являются стандартными числовыми представлениями.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги