ToString ( "0" ) по сравнению с ToString (CultureInfo.InvariantCulture)
Я хотел бы удостовериться, что определенные числа в моем приложении печатаются без каких-либо разделителей, групп и т.д., независимо от текущей среды. Кажется, что следующие два метода дают одинаковые результаты (возможно, больше):
123456789.ToString("0");
123456789.ToString(CultureInfo.InvariantCulture);
Знаете ли вы о каких-либо случаях кромки или причудах? Какой из них более "правильный"? Какой из них вы бы использовали?
Я использовал второй, но недавно я нашел первый и начал использовать его, потому что он не требует дополнительного using System.Globalization
.
Ответы
Ответ 1
Основываясь на ответах и обсуждении здесь, я сделал еще несколько исследований. Вот что я нашел:
-
Когда вы используете 12345678.ToString()
без каких-либо аргументов,.NET использует общий спецификатор общего формата "G" , на который влияет только NumberFormatInfo.NegativeSign, NumberFormatInfo. NumberDecimalSeparator, NumberFormatInfo.NumberDecimalDigits и NumberFormatInfo.PositiveSign. Для меня это говорит о том, что в любой культуре 12345678.ToString()
должен всегда производиться "12345678".
-
Если вы хотите разделить цифры, вам нужно использовать спецификатор числового формата N " (или, конечно же, предоставить строку пользовательского формата). Группировка цифр также относится к" C "и" P".
-
инвариантная культура действительно определяет группировку цифр (на 3 цифры, конечно) и разделитель цифр. Поэтому причина, по которой 123456789.ToString(CultureInfo.InvariantCulture)
производит "123456789", происходит не из-за инвариантной культуры, а из-за стандартного спецификатора числового формата "G".
Итак, я бы сказал, что вывод состоит в том, что его совершенно нормально не беспокоиться о любых дополнительных аргументах и просто использовать:
12345678.ToString()
Я думаю, что это лучшее из всех случаев, потому что это означает, что обычно вам не нужно даже звонить ToString()
, потому что большинство функций print/write принимают всевозможные аргументы и делают ToString()
для вас.
Ответ 2
Два метода не эквивалентны: первый использует CurrentCulture. Это может привести к дополнительным точкам/запятым в определенных культурах (у меня нет примеров).
При использовании InvariantCulture вы уверены, что всегда используется одинаковое форматирование.
Изменить: И если вы используете CodeAnalysis, это будет жаловаться, если вы не используете CultureInfo.
Ответ 3
Как я вижу, первый формат будет содержать число с хотя бы одним символом, использующим культуру по умолчанию компьютера.
Второй будет отформатировать его как число в зависимости от правил InvariantCulture.
Бобби
Ответ 4
2 строки делают разные вещи. Первая строка форматирует число с локальной культурой, а вторая преобразует его в строку без форматирования, но использует CultureInfo.InvariantCulture.
Вы используете CultureInfo.InvariantCulture с такими методами (ToString, ToLower...), чтобы убедиться, что, когда значение используется любым программным обеспечением (база данных, другая библиотека...), независимо от их культуры, это приведет к тому же значению, и когда они смогут поднять это значение, они могут продолжить его обработку. Однако, если вы не используете это, другое программное обеспечение должно выяснить, что такое ваша культура. Вы имели в виду десятичный разделитель с запятой или что-то еще...?
Все и вся используют CultureInfo.InvariantCulture, когда вы хотите обменивать/использовать значения между библиотеками, базами данных и использовать CultureInfo.CurrentCulture для показа пользователям вашего приложения.
// for softwares
string mystring1 = 1234.ToString("0", CultureInfo.InvariantCulture);
// for your application users
string mystring2 = 1234.ToString("0", CultureInfo.CurrentCulture);
Ответ 5
(~ 5 лет спустя...)
Я искал этот точный вопрос, но поскольку ответа не было принято, и хотя Ян Зич прав, я подумал, что придумаю небольшой пример, чтобы проверить это.
Я бы также сказал, что нет никакой разницы между .ToString(),.ToString( "0" ) и .ToString(любая информация о культуре) (в отношении целых чисел и десятичных знаков)
var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures)
.Except(CultureInfo.GetCultures(CultureTypes.SpecificCultures));
foreach(var c in cultures){
var num = (int.MinValue);/*
var num = (int.MaxValue);/*
var num = (decimal.MinValue);/*
var num = (decimal.MaxValue);/*
--*/
var s1 = num.ToString("0") ;
var s2 = num.ToString(c);
if(s1 != s2){
var s = string.Format("{2}: {0} {1}",s1,s2,c);
s.Dump();
}
}
фрагмент LinqPad
Ответ 6
Если вы хотите указать "нет форматирования, независимо от того, что лично я считаю первым, у вас есть:
123456789.ToString("0");
лучше сообщает намерение. Недостатком будет то, что если культура изменит строку формата "0" для используемого числового типа.
Ответ 7
.ToString() и .ToString(CultureInfo.InvariantCulture) всегда дают одинаковый результат для целых чисел.
В приведенном ниже коде " опрошено 809 культур, обнаружено 0 различий" на моем ПК:
var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures).ToArray();
var numbers = new[] { 0, -1, 1, int.MinValue, int.MaxValue };
var diffsFound = 0;
foreach (var culture in cultures)
{
foreach (var number in numbers)
{
var s1 = number.ToString();
var s2 = number.ToString(culture);
if (s1 != s2)
{
Console.WriteLine($"{culture.DisplayName}: {s1} != {s2}");
diffsFound++;
}
}
}
Console.WriteLine($"{cultures.Length} cultures tested, {diffsFound} differences found.");