Похоже, что многие ответы на этот вопрос включают замену символа процента культуры пустой строкой, а затем синтаксический анализ полученной строки в виде числового значения.
Возможно, я что-то упускаю, но здесь все еще есть некоторые необработанные случаи. В частности, что произойдет, если PercentDecimalSeparator
отличается от NumberDecimalSeparator
для текущей культуры? Что произойдет, если PercentGroupSeparator
отличается от NumberGroupSeparator
для текущей культуры? Что произойдет, если PercentGroupSizes
отличается от NumberGroupSizes
?
Независимо от того, существует ли такая культура на практике (если она не существует, она вполне может появиться в будущем, если форматирование культуры будет изменено), я думаю, что лучшее решение проблемы можно найти, если мы рассмотрим эти дополнительные, особые случаи.
Вот фрагмент кода, который показывает ситуацию, в которой другие ответы (основанные только на замене символа процента), терпят неудачу, и предложение того, как это можно сделать лучше правильно:
// Modify a culture so that it has different decimal separators and group separators for numbers and percentages.
var customCulture = new CultureInfo("en-US")
{
NumberFormat = { PercentDecimalSeparator = "PDS", NumberDecimalSeparator = "NDS", PercentGroupSeparator = "PGS", NumberGroupSeparator = "NGS", PercentSymbol = "PS"}
};
// Set the current thread's culture to our custom culture
Thread.CurrentThread.CurrentCulture = customCulture;
// Create a percentage format string from a decimal value
var percentStringCustomCulture = 123.45m.ToString("p");
Console.WriteLine(percentStringCustomCulture); // renders "12PGS345PDS00 PS"
// Now just replace the percent symbol only, and try to parse as a numeric value (as suggested in the other answers)
var deceptiveNumericStringInCustomCulture = percentStringCustomCulture.Replace(customCulture.NumberFormat.PercentSymbol, string.Empty);
// THE FOLLOWING LINE THROWS A FORMATEXCEPTION
var decimalParsedFromDeceptiveNumericStringInCustomCulture = decimal.Parse(deceptiveNumericStringInCustomCulture);
// A better solution...replace the decimal separators and number group separators as well.
var betterNumericStringInCustomCulture = deceptiveNumericStringInCustomCulture.Replace(customCulture.NumberFormat.PercentDecimalSeparator, customCulture.NumberFormat.NumberDecimalSeparator);
// Here we mitigates issues potentially caused by group sizes by replacing the group separator by the empty string
betterNumericStringInCustomCulture = betterNumericStringInCustomCulture.Replace(customCulture.NumberFormat.PercentGroupSeparator, string.Empty);
// The following parse then yields the correct result
var decimalParsedFromBetterNumericStringInCustomCulture = decimal.Parse(betterNumericStringInCustomCulture)/100m;
Да, код немного длиннее, и, возможно, я педантичен (то есть, возможно, такая культура никогда не будет существовать). Тем не менее, мне кажется, это более общее решение. Надеюсь, это кому-нибудь поможет:).