13

Consider the following Console App code:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

DateTime date = new DateTime(2014, 01, 19);

Console.WriteLine("{0}", date); // Prints 19/01/2014
Debug.WriteLine("{0}", date);   // Prints 01/19/2014
Debug.WriteLine(date);          // Prints 19/01/2014

As noted in the comments, the Console.WriteLine() prints 19/01/2014 while the Debug.WriteLine() prints 01/19/2014.

Even worse - Debug.WriteLine("{0}", date) gives different output from Debug.WriteLine(date)...

Is it expected that Debug.WriteLine() ignores the thread's culture settings?

Is there a way to make Debug.WriteLine() use the thread's culture settings? Or must I use String.Format() and pass the result to Debug.WriteLine()?

(Note: I'm running this on Windows 8.1 64-bit, en-GB, using Visual Studio 2013 with .Net 4.51 with a debug AnyCPU build.)

Yuval Itzchakov
  • 136,303
  • 28
  • 230
  • 296
Matthew Watson
  • 90,570
  • 7
  • 128
  • 228

2 Answers2

12

This is explicitly handled in the source.

It makes sense, too.
Debug output should not be affected by the end-users culture; you want your debug logs to be consistent no matter where the code is running.

SLaks
  • 800,742
  • 167
  • 1,811
  • 1,896
  • 5
    Well, I've marked this as the answer, but I don't agree with the reasoning. Firstly, debug output will never occur on an end-user's computer (because it would be a release build, not a debug build). Secondly, I want to have the dates in UK format so I don't mix them up. Thirdly, it's common to use `string.Format()` to format messages for `Debug.WriteLine()`, so by mixing this you can get different outputs depending on whether you used `string.Format()` to construct an interim string. – Matthew Watson Jan 19 '15 at 16:08
  • 2
    And even worse, `Debug.WriteLine(date)` gives you a different result from `Debug.WriteLine("{0}", date)`! – Matthew Watson Jan 19 '15 at 16:11
  • 1
    @MatthewWatson Debug output will (hopefully) never occur on an end user's PC ... but it could easily come from multiple developer PC's where the developers are in several different countries. In that scenario, I would want all the machines to be using the same culture settings. – David Jan 19 '15 at 22:30
  • 1
    This explains why Debug and Console are different, but not why `Debug.WriteLine("{0}", date);` is different from `Debug.WriteLine(date);`. Could you add a sentence about that? – Ixrec Jan 19 '15 at 22:56
  • @Ixrec: That's actually handled by the listeners. http://referencesource.microsoft.com/#System/compmod/system/diagnostics/TraceInternal.cs,482 They probably call `ToString()` directly. – SLaks Jan 19 '15 at 23:09
  • @David And equally you could easily use `Debug.WriteLine(object)` in one case and `Debug.WriteLine(format, args)` in another - with different results. Clearly there is inconsistency here. Should the advice be to NEVER use `Debug.WriteLine(object)`? – Matthew Watson Jan 20 '15 at 09:13
  • @MatthewWatson I think the point is that whether you use `Debug.WriteLine(object)` or `Debug.WriteLine(format, args)`, in either / each case the output would be consistent regardless of culture. As to the two overloads generating different output ... an argument could be made that debug / trace code should use one or the other, consistently. I'm not saying *I* would make that argument -- I tend to agree with you that this is bad UX -- but I'm pretty sure some of my present & former co-workers would do. – David Jan 20 '15 at 15:49
10

The overload you are using explicitly ignores the culture by using InvariantCulture:

public static void WriteLine(string format, params object[] args) 
{
    TraceInternal.WriteLine(String.Format(CultureInfo.InvariantCulture, format, args));
}

All the other overloads don't do anything related to culture. You can "workaround" this by using the overload which takes a string:

public static void WriteLine(string message, string category)
{
    TraceInternal.WriteLine(message, category);
}

By doing this:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

DateTime date = new DateTime(2014, 01, 19);

var formatedDate = string.Format("{0}", date);
Console.WriteLine(formatedDate);
Debug.WriteLine(formatedDate);

Now both print:

19/01/2014 00:00:00 
19/01/2014 00:00:00
Yuval Itzchakov
  • 136,303
  • 28
  • 230
  • 296