2009-09-28 32 views
13

Ich möchte sicherstellen, dass bestimmte Zahlen in meiner Anwendung ohne Trennzeichen, Gruppierungen usw. gedruckt werden, unabhängig von der aktuellen Umgebung. Es scheint, dass die folgenden zwei Methoden, um die gleichen Ergebnisse zu erzielen (es gibt möglicherweise mehr):ToString ("0") versus ToString (CultureInfo.InvariantCulture)

123456789.ToString("0"); 
123456789.ToString(CultureInfo.InvariantCulture); 

Sind Sie Kenntnis von irgendwelchen Randfällen oder Macken? Welcher ist "richtiger"? Welchen würdest du benutzen?

Ich benutzte die zweite, aber vor kurzem fand ich die erste und begann damit, weil es nicht die zusätzliche using System.Globalization erfordert.

Antwort

0

Wenn Sie wollen sicherstellen, dass „keine Formatierung, egal, was“ an, ich persönlich denke, die erste Option, die Sie haben:

123456789.ToString("0"); 

besser die Absicht in Verbindung steht. Der Nachteil wäre, wenn eine Kultur die Formatzeichenfolge "0" für den von Ihnen verwendeten numerischen Typ überschreiben würde.

+0

Oh, wusste ich jetzt, dass Sie die Formatstrings außer Kraft setzen können? Ich muss nachsehen. –

+0

Sind Sie sicher über die Überladung? MSDN (http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx) sagt: "Jedes andere einzelne Zeichen [als eine dieser Standardzeichen] löst zur Laufzeit eine FormatException aus." –

+0

Ich war mir nicht sicher, ob das der Fall war oder nicht. Ich sehe einen schnellen Ausflug in die MSDN Library hätte mir das gezeigt :). –

2

Wie ich es sehe, ist das erste Format eine Zahl mit mindestens einem Zeichen unter Verwendung der Standardkultur des Computers. Die zweite wird es als eine Zahl in Abhängigkeit von den InvariantCulture-Regeln formatieren.

Bobby

+0

Korrigieren Sie mich, wenn ich falsch liege: Ich dachte, dass keine Zifferngruppierung, Trennzeichen etc. für 123456789.ToString ("0") gelten? –

+0

Uhhh ... tut es wirklich nicht. Ich habe es für ein Formatierungssymbol wie "N0" verwechselt, das die aktuellen Kulturregeln anwendet. Sie haben recht, da die 0 eine direkte Formatierung ist, gelten keine _any_ Kulturinformationen. Obwohl jemand könnte auch verwenden 123456789.ToString(); . – Bobby

5

Die beiden Verfahren sind nicht äquivalent: die erste die Current verwendet. Dies könnte in bestimmten Kulturen zu zusätzlichen Punkten/Kommas führen (ich habe keine Beispiele).

Wenn Sie InvariantCulture verwenden, sind Sie sicher, dass immer die gleiche Formatierung verwendet wird.

Edit: Und wenn Sie CodeAnalysis verwenden, wird sich dies beschweren, wenn Sie keine CultureInfo verwenden.

+0

Ich testete die erste, indem ich die aktuelle Thread-Kultur änderte, und sie hat es nicht beeinflusst. Ich denke, die "0" bedeutet: mindestens eine Ziffer + keine Zifferngruppierung oder Trennzeichen. Wenn ich eine Zifferngruppierung oder Trennzeichen haben wollte, müsste ich wohl so etwas wie "000,000" machen. –

+2

Aber Sie haben Recht: InvariantCulture "klingt" expliziter. Sogar MSDN sagt "... es ist mit der englischen Sprache verbunden, aber nicht mit irgendeinem Land/Gebiet". Hmm, wenn ich darüber nachdenke, ToString (CultureInfo.InvariantCulture), bedeutet dies, dass die Zahl, wenn sie mit dem "G" formatiert wird. Es funktioniert nur zufällig, weil "G" anscheinend keine Gruppierung verwendet. ABER (ich habe gerade nachgeschaut) die invariante Kultur hat eine bestimmte Gruppierung. Versuchen Sie beispielsweise 12345789.ToString ("N", CultureInfo.InvariantCulture). –

17

Basierend auf den Antworten und der Diskussion hier, habe ich weitere Untersuchungen durchgeführt. Hier ist, was ich gefunden habe:

  • Wenn Sie 12345678.ToString() ohne Argumente verwenden, verwendet .NET allgemein die allgemeinen Formatbezeichner „G“, die nur durch NumberFormatInfo.NegativeSign, Number betroffen ist. NumberDecimalSeparator, NumberFormatInfo.NumberDecimalDigits und NumberFormatInfo.PositiveSign. Für mich heißt das, dass in jeder Kultur 12345678.ToString() immer "12345678" produzieren soll.

  • Wenn Sie separate Ziffern wollen, müssen Sie die numerische Formatbezeichner verwenden „N“ (oder, natürlich, einen benutzerdefinierten Format-String zur Verfügung zu stellen). Die Zifferngruppierung gilt auch für "C" und "P".

  • Die invariante Kultur spezifiziert tatsächlich Ziffer (von 3 Ziffern, natürlich) und eine Ziffer Separator Gruppierung. Der Grund, dass 123456789.ToString(CultureInfo.InvariantCulture) "123456789" erzeugt, liegt nicht an der invarianten Kultur, sondern am Standard-numerischen Formatbezeichner "G".

Also ich würde sagen, dass die Schlussfolgerung ist, dass es völlig in Ordnung ist nicht über irgendwelche zusätzlichen Argumente zu kümmern und verwenden nur:

12345678.ToString() 

Ich denke, dass dies die beste von allen Fällen weil es bedeutet, dass Sie normalerweise nicht einmal ToString() aufrufen müssen, weil die meisten der Druck-/Schreibfunktionen alle möglichen Argumente akzeptieren und die ToString() für Sie erledigen.

1

2 Zeilen machen verschiedene Dinge. Die erste Zeile formatiert die Nummer mit der lokalen Kultur und die zweite Zeile konvertiert sie in eine Zeichenfolge ohne Formatierung, aber mit CultureInfo.InvariantCulture.

Sie verwenden CultureInfo.InvariantCulture mit dieser Art von Methoden (ToString, ToLower ...), um sicherzustellen, dass, wenn der Wert von einer Software (Datenbank, eine andere Bibliothek ...) verwendet wird, egal was ihre Kultur ist , es wird den gleichen Wert ergeben und wenn sie diesen Wert aufnehmen können, können sie weiter verarbeiten. Wenn Sie dies jedoch nicht verwenden, muss die andere Software herausfinden, was Ihre Kultur ist. Meinst du Dezimaltrennzeichen mit Komma oder etwas anderes ...?

Alle verwenden CultureInfo.InvariantCulture, wenn Sie Werte zwischen Bibliotheken und Datenbanken austauschen/verwenden und CultureInfo.CurrentCulture den Benutzern Ihrer Anwendung anzeigen möchten.

// for softwares 
string mystring1 = 1234.ToString("0", CultureInfo.InvariantCulture); 

// for your application users 
string mystring2 = 1234.ToString("0", CultureInfo.CurrentCulture); 
1

(~ 5 Jahre später ...)

Ich war genau diese Frage nach oben, aber da es keine akzeptierte Antwort war und obwohl Jan Zich korrekt Ich dachte, ich würde ein wenig zusammen Beispiel, um dies zu testen.

Ich würde auch so weit gehen zu sagen, dass es keinen Unterschied zwischen .ToString(), .ToString ("0") und .ToString (Any Culture Info) gibt (soweit Ganzzahlen und Dezimalzahlen betreffen)

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 snippet

0

die .ToString() und .ToString (CultureInfo.InvariantCulture) immer das gleiche Ergebnis für ganze Zahlen geben.

Der folgende Code gibt „809 Kulturen getestet, 0 Unterschiede gefunden“ Ergebnis auf meinem PC:

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