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.");