title: Overriding ToString() for debugging and logs - should the string be localized?
body: <p>I'm designing a .NET library that will be used by other developers making both web and desktop applications.  I'm overriding <code>ToString()</code> in various classes to provide information for debugging purposes and for inclusion in application log files.</p>
  
  <p>Some of my classes contain numbers and dates.</p>
  
  <p>Consider an object that contains a <code>DateTime</code> called <code>date</code> and a <code>double</code> called <code>value</code> (and maybe other fields as well)...  If I override that object's <code>ToString()</code>, I might want to do something like:</p>
  
  <pre><code>public override string ToString() {
      return "ObjectName[date=" + date + ", value=" + value + "]";
  }
  </code></pre>
  
  <p>But that will include the result from <code>date.ToString()</code> and <code>value.ToString()</code>, which will give me strings that are localized according to <code>Thread.CurrentThread.CurrentCulture</code>.</p>
  
  <p>And that, to me, seems wrong.  The strings returned by my <code>ToString()</code> implementations are meant for debugging and log messages, not for user interfaces.  So I think returning localized strings could only confuse matters.  If "2,341" appears in log files, a developer would need to know the value of the thread's <code>CurrentCulture</code> to know whether it meant 2 thousand 341 or 2 point 341.  It's even more confusing with dates - a string like xx/xx/xxxx could be dd/mm/yyyy or mm/dd/yyyy.  I don't want my <code>ToString()</code> methods to create that sort of ambiguity.</p>
  
  <p>So my inclination is to make my <code>ToString()</code> methods culture-insensitive, to ensure that all returned strings are consistent across cultures.  For example, internally my <code>ToString()</code> methods would do like <code>value.ToString(CultureInfo.InvariantCulture)</code> to format a number. </p>
  
  <p>However, the norm in .NET libraries seems to be to use <code>CurrentCulture</code> in default no-args <code>ToString()</code> implementations.  Many objects that have a <code>ToString()</code> method also have a <code>ToString(IFormatProvider)</code> method as well.  It's as if the designers of .NET decided that the default use of <code>ToString()</code> should be for user-interface display (localized), and that debugging and logs (for which you'd need to call <code>ToString(CultureInfo.InvariantCulture)</code>) are secondary.</p>
  
  <p>So if I implement my <code>ToString()</code> methods in a culture-insensitive way, I feel I'd be going against the grain somewhat.  But it seems silly to create culture-sensitive strings by default, when culture-sensitivity makes no sense for log files or debugging.</p>
  
  <p>I could use the <code>CurrentCulture</code> to represent numbers and dates in my default <code>ToString()</code> implementations, and also provide <code>ToString(FormatProvider)</code> methods so that people can get a culture-insensitive string for use in log files etc.  But that seems dumb as it's just forcing developers to write more code to get the culture-insensitive string that I'm guessing they'll want (whether they've considered it or not).</p>
  
  <p>The bottom line is that a string like <code>ObjectName[value=12.234, date=2011-10-01]</code> shouldn't ever appear in a user interface, so why would a programmer ever want it to be localized?</p>
  
  <p>I've been reading the advice in Framework Design Guidelines on implementing <code>ToString()</code>.  Some of the advice seems somewhat contradictory.  For example:</p>
  
  <blockquote>
    <p>I consider <code>ToString</code> an especially dangerous method to provide for UI-generic types, because it's likely to be implemented with some specific UI in mind, making it useless for other UI needs.  To avoid tempting myself in this way, I prefer to make my <code>ToString</code> output as geeky as possible to emphasize that the only "humans" that should ever see the output are "developer humans" (a subspecies all their own).</p>
  </blockquote>
  
  <p>and</p>
  
  <blockquote>
    <p>The most important value of <code>ToString</code> is that the debugger uses it as the default way of displaying the object.</p>
  </blockquote>
  
  <p>don't really seem to fit with:</p>
  
  <blockquote>
    <p><strong>DO</strong> string formatting based on the current thread culture when returning culture-dependent information.</p>
  </blockquote>
  
  <p>and</p>
  
  <blockquote>
    <p>use the <code>CultureInfo</code> instance returned by a thread's <code>CurrentCulture</code> property to format any numeric or date</p>
  </blockquote>
  
  <p>I'm all for following the guidelines, and writing APIs that do what programmers expect.  But if <code>ToString()</code> is for programmers, then it seems silly to localize it.  The C# compiler won't let a programmer write a double literal using a system-dependent decimal separator, so surely <code>ToString()</code> methods written for programmers should behave similarly?</p>
  
  <p>What do you think?  <strong>When the output from <code>ToString()</code> is <em>not</em> intended for use in a user-interface, should the numbers and dates within it be localized or not?</strong></p>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <p>I did some tests using the <code>DebuggerDisplay</code> attribute, and it looks like, by default, it formats numbers in a culture-insensitive way.</p>
  
  <pre><code>[DebuggerDisplay("[value={value}]")]
  class DoubleHolder {
      private double value;
      DoubleHolder(double value) {
          this.value = value;
      }
  }
  
  [TestMethod]
  public void TestDebuggerValue() {
      DoubleHolder s = new DoubleHolder(12345678.12345);
      string doubleString = TestDouble.ToString();
      CultureInfo current = Thread.CurrentThread.CurrentCulture;
      Thread.CurrentThread.CurrentUICulture = current;
      CultureInfo ui = Thread.CurrentThread.CurrentUICulture;
      Debugger.Break();
  }
  </code></pre>
  
  <p>Run that test in the debugger and, when it breaks you can see that the <code>double</code> contained in <code>DoubleHolder</code> is formatted with a <code>.</code> as a decimal separator.</p>
  
  <p>Then close Visual Studio, change your windows Regional Options for Standards and Formats to French, say, and run the test again.  You'll see that <code>doubleString</code> has a <code>,</code> as the decimal separator, but the the debugger still shows the <code>double</code> in <code>DoubleHolder</code> with a <code>.</code></p>
  
  <p>I would have liked to test this on a proper French version of Windows, with Visual Studio in French.  In Visual Studio, if you go to Tools -> Options -> Environment -> International Settings, you can set the Language to "Same as Microsoft Windows".  By default on my installation it was set to "English".  But to get Visual Studio in French you need to have Windows in French, and my version of Windows seems to be English only.  If anyone has a French Windows, or any other locale that uses <code>,</code> as a decimal separator, it'd be great if you could just check whether the debugger uses <code>.</code> or <code>,</code> as the decimal separator in formatted doubles.</p>
  
  <p>I'm wondering if <code>Thread.CurrentThread.CurrentUICulture</code> might make a difference to how the Visual Studio debugger shows things, and I'm not sure that setting it like I do above would be the same as running Visual Studio completely in French.</p>
  
  <p>But from the above it does look like the debugger consistently uses <code>.</code> as the decimal separator.  This implies to me that a culture-independent ToString() method is fine, probably preferable, if it's intended for debugging purposes.</p>