Я пытаюсь использовать Decimal.TryParse, чтобы вернуть описательное сообщение пользователю, когда значение не работает (в фактическом коде я передаю номер элемента, который пользователь может затем использовать, чтобы вернуться и исправить). Тем не менее, 3,5, похоже, подходит для Decimal.TryParse (3,5 было опечаткой 3,5. Я знаю, что обычно в США запятые нужны для простоты чтения и безопасно игнорируются, хотя обычно разделяются блоками по 3 справа налево. слева, начиная с десятичного знака), тогда как когда я использую NumberStyles с Parse, это не так. Как я могу получить 3,5, чтобы не выполнить синтаксический анализ попытки?
using System.Globalization;
string test = "3,5";
Decimal val;
if (!Decimal.TryParse(test, out val))
{
throw new Exception("Error: " + test + " is not valid.");
}
// at this point, val is now '35'
val = Decimal.Parse(test, NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint); // fails
Console.WriteLine(val);
Или мой лучший способ действий - переписать if для проверки запятой?
if (!Decimal.TryParse(test, out val) || test.Contains(","))
Не могли бы вы отредактировать вопрос с минимально воспроизводимым примером вашей попытки использовать соответствующий TryParse? Пока совершенно непонятно, как у вас не сработала передача NumberStyles в TryParse...
if (!Decimal.TryParse(test, NumberStyles.Float, null, out val)) {... ?
@AlexeiLevenkov ОП хочет, чтобы наличие запятой приводило к тому, что TryParse давал результат false. Код в вопросе демонстрирует, что это не так с используемой перегрузкой. Может быть, они не знали о перегрузке, которую я указал в своем предыдущем комментарии.
Результат выполнения этого кода зависит от текущей культуры.
var provider = new NumberFormatInfo { NumberGroupSeparator = "" }; if (!Decimal.TryParse(test, provider, out val)) - Укажите поставщика формата, в котором отсутствует разделитель групп.
@ Эндрю Мортон прав. Я пытался найти Decimal.TryParse(string, NumberStyles, out Decimal), аналогичный Decimal.Parse, но когда я попытался, IDE показывает только (string, IFormatProvider, out Decimal).





Вы всегда должны использовать перегрузку для TryParse, которая принимает аргумент IFormatProvider или, скорее, культуру.
Чаще всего используется одна из двух форм:
if (Decimal.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, out var number)
{
// ....
}
или
if (Decimal.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)
{
// ....
}
Первый формат используется, когда данные для синтаксического анализа вводятся пользователем и ожидается, что они будут в языковом стандарте пользователя. Таким образом, в зависимости от того, где вы находитесь, точка будет либо десятичным разделителем, либо разделителем тысяч. Или ни то, ни другое. Второй формат используется, если данные, например. из файла и всегда имеет один и тот же формат. Он использует '.' в качестве десятичного разделителя (и ',' в качестве разделителя тысяч, но в данном случае он обычно не используется).
Кроме того, вы можете указать свои собственные настройки пользовательского формата, либо указав явный NumberFormatInfo, например, var provider = new NumberFormatInfo { NumberGroupSeparator = "" }; или путем предоставления определенной культуры, например. с CultureInfo us = new CulturInfo("en-US");.
Таким образом, нет «одного правильного» решения, это зависит от контекста и того, что предполагает пользователь.
Как я могу получить 3,5, чтобы не выполнить синтаксический анализ попытки?
Простой ответ — отключить флаг «AllowThousands» в NumberStyles. Например:
decimal.TryParse(test, NumberStyles.Any ^ NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out val)
Если вы хотите, чтобы поведение TryParse совпадало с поведением Parse, вам нужно использовать те же NumberStyles в TryParse, что и в Parse. TryParse не имеет перегрузки, которая принимает NumberStyles без использования IFormatProvider, но вы можете явно передать null в аргумент IFormatProvider, чтобы получить такое же поведение.
string test = "3,5";
Decimal val;
if (!Decimal.TryParse(
test,
NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint,
null,
out val))
{
throw new Exception("Error: " + test + " is not valid.");
}
Console.WriteLine(val);
По умолчанию без IFormatProvider используется текущий язык и региональные параметры, что может привести к неожиданному поведению и сложно воспроизводимым ошибкам. Рассмотрите возможность использования CultureInfo.InvariantCulture или, возможно, конкретной культуры, которая имеет поведение, которому вы хотите соответствовать.
Я считаю, что вам нужно указать конкретную культуру в качестве третьего параметра.