2014-06-18 9 views
6

Angesichts der folgenden C# -Code:Interpretieren Termine: Console.WriteLine vs. string.Format

var dt = DateTime.Now; 
Console.WriteLine("{0:MM/dd/yy} ... {1}", dt, string.Format("{0:MM/dd/yy}", dt)); 

... wenn das kurze Datum (unter Windows 7, Control Panel -> Region and Language -> Additonal Settings -> Date) in die USA Standard "M/d/yyyy gesetzt „ich bekomme diese:

06/17/14 ... 06/17/14 

Allerdings, wenn ich das kurze Datum ändern " ddd dd MMM yyyy," ich diese:

06/17/14 ... 06 17 14 

Ich hatte den Eindruck, dass und string.Format immer string formatiert DateTime Werte identisch sind. Was ist die Erklärung für diese Diskrepanz?

EDIT: Sieht aus wie dies geschieht nur in Standard-Unit-Test-Ausgabe (Visual Studio), wo ich ursprünglich das Problem sah. Wenn der Code in einer Konsolenanwendung ausgeführt wird, lautet die Ausgabe 06 17 14 ... 06 17 14.

+0

Es ist nicht wichtig, was Ihre Systemeinstellungen sind, wenn Sie die Formatzeichenfolge explizit festlegen. Ich denke, hier ist etwas anderes los. – Enigmativity

+0

Tatsächlich kann dies von Bedeutung sein, da die "/" keine wörtlichen Zeichen, sondern Trennzeichen sind und die tatsächliche Ausgabe von der Kultur abhängt, z. In Deutschland wäre es ein ".". Aber das erklärt nicht, warum die Ausgabe anders ist, wenn dasselbe explizite Format in 'Console.WriteLine' und' String.Format' verwendet wird. – Dirk

+0

@Enigmatismus: Nun, das Ändern des kurzen Datums bedeutet anscheinend, die Kultur zu ändern, was .NET betrifft. Ich frage mich nur, warum die beiden Methodenaufrufe sich nicht gleich verhalten. – MiloDC

Antwort

3

Diese Situation tritt auf, da, wenn MSTest Konsolausgabe an das Testfenster umleitet, übergibt es CultureInfo.InvariantCulture an die TextWriter, die der Konsole zugeordnet ist.

Sie können dies überprüfen, mit dem folgenden:

var threadCulture = Thread.CurrentThread.CurrentCulture; 
var consoleCulture = Console.Out.FormatProvider; 

Console.WriteLine(threadCulture.Equals(CultureInfo.InvariantCulture)); 
Console.WriteLine(consoleCulture.Equals(CultureInfo.InvariantCulture)); 

Sofern Sie es nicht ändern, dem aktuellen Kultur des Threads in der Regel wie en-US etwas ist, oder was auch immer Ihr Computer eingestellt ist. Also wird der erste Gegenstand normalerweise falsch sein.

Aber das zweite Element variiert je nachdem, wo es abläuft. Als Konsolenanwendung sollte die Konsolenausgabekultur standardmäßig der aktuellen Thread-Kultur entsprechen - daher wird sie falsch sein. In XUnit- oder NUnit-Tests ist das Ergebnis ebenfalls falsch. Aber in MSTest ist das Ergebnis wahr.

Wenn Sie die .NET Framework Reference Source graben, werden Sie, dass

Ich glaube nicht, die Quellen für die MSTest Testläufer ist öffentlich zugänglich, aber man kann feststellen, dass sie irgendwo etwas tun müssen, wie:

Console.Out = new SomeWriter(CultureInfo.InvariantCulture); 

Wo SomeWriter die Test-Ausgabe erstellt und erbt von TextWriter.

Auf der anderen Seite wird String.Format immer die aktuelle Kultur des Threads verwenden, es sei denn, Sie stellen speziell eine andere Kultur zur Verfügung.

Eine Möglichkeit, um dies zu umgehen, wäre, die aktuelle Kultur des Threads explizit auf die invariante Kultur zu setzen.

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; 
+0

Danke für die Erklärung, Matt! – MiloDC

+1

Danke für die tolle Frage! –

1

Dies liegt daran, wie die Format Methode das / Symbol interpretiert.

Von MSDN

Wenn ein benutzerdefinierten Format-String der "/" Formatbezeichner enthält, zeigt die DateTime.ToString Methode den Wert von DateSeparator anstelle der "/" in der Ergebniszeichenfolge.

Die DateSeparator-Eigenschaft definiert die Zeichenfolge, die das Datumstrennzeichen ("/" benutzerdefinierter Datums- und Zeitformatbezeichner) in einer Ergebniszeichenfolge in einem Formatierungsvorgang ersetzt. Es definiert auch die Datumstrennzeichenfolge in einer Parsing-Operation.

Wenn Sie das Format ändern, wird das Standardsymbol in ein Leerzeichen geändert.

Wenn das Zeichen / angezeigt werden muss, kann es durch Verwendung von \ ausgeblendet werden. Wenn Sie also die Formatzeichenfolge auf {0:MM\/dd\/yy} ändern, wird immer / angezeigt.

+0

Ich weiß das schon. Das Problem, dass der Schrägstrich nicht in Whitespace geändert wird, besteht darin, dass die beiden Methodenaufrufe zu unterschiedlichen Ergebnissen führen. Wie ich festgestellt habe, scheint dies nur in der Testausgabe zu geschehen. – MiloDC