简体   繁体   English

覆盖ToString()以进行调试和日志 - 字符串是否应该本地化?

[英]Overriding ToString() for debugging and logs - should the string be localized?

I'm designing a .NET library that will be used by other developers making both web and desktop applications. 我正在设计一个.NET库,供其他开发人员使用Web和桌面应用程序。 I'm overriding ToString() in various classes to provide information for debugging purposes and for inclusion in application log files. 我在各种类中重写ToString() ,以提供用于调试目的和包含在应用程序日志文件中的信息。

Some of my classes contain numbers and dates. 我的一些课程包含数字和日期。

Consider an object that contains a DateTime called date and a double called value (and maybe other fields as well)... If I override that object's ToString() , I might want to do something like: 考虑包含一个对象DateTime名为datedouble名为value (也许其他领域也一样)......如果我重写该对象的ToString() ,我可能想要做的是这样的:

public override string ToString() {
    return "ObjectName[date=" + date + ", value=" + value + "]";
}

But that will include the result from date.ToString() and value.ToString() , which will give me strings that are localized according to Thread.CurrentThread.CurrentCulture . 但是这将包括date.ToString()value.ToString() ,它将为我提供根据Thread.CurrentThread.CurrentCulture进行本地化的字符串。

And that, to me, seems wrong. 那对我来说,似乎是错的。 The strings returned by my ToString() implementations are meant for debugging and log messages, not for user interfaces. 我的ToString()实现返回的字符串用于调试和日志消息,而不是用户界面。 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 CurrentCulture 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. 如果日志文件中出现“2,341”,开发人员需要知道线程的CurrentCulture的值才能知道它是否意味着2千341或2分341.它更令人困惑的日期 - 像xx / xx / xxxx这样的字符串可能是dd / mm / yyyy或mm / dd / yyyy。 I don't want my ToString() methods to create that sort of ambiguity. 我不希望我的ToString()方法产生那种歧义。

So my inclination is to make my ToString() methods culture-insensitive, to ensure that all returned strings are consistent across cultures. 所以我倾向于使我的ToString()方法对文化不敏感,以确保所有返回的字符串在不同文化中是一致的。 For example, internally my ToString() methods would do like value.ToString(CultureInfo.InvariantCulture) to format a number. 例如,我的ToString()方法内部会像value.ToString(CultureInfo.InvariantCulture)格式化数字。

However, the norm in .NET libraries seems to be to use CurrentCulture in default no-args ToString() implementations. 但是,.NET库中的规范似乎是在默认的无参数ToString()实现中使用CurrentCulture Many objects that have a ToString() method also have a ToString(IFormatProvider) method as well. 许多具有ToString()方法的对象也具有ToString(IFormatProvider)方法。 It's as if the designers of .NET decided that the default use of ToString() should be for user-interface display (localized), and that debugging and logs (for which you'd need to call ToString(CultureInfo.InvariantCulture) ) are secondary. 就好像.NET的设计者决定默认使用ToString()应该是用户界面显示(本地化),调试和日志(你需要调用ToString(CultureInfo.InvariantCulture) )是次要的。

So if I implement my ToString() methods in a culture-insensitive way, I feel I'd be going against the grain somewhat. 因此,如果我以一种对文化不敏感的方式实现我的ToString()方法,我觉得我会反对这种方式。 But it seems silly to create culture-sensitive strings by default, when culture-sensitivity makes no sense for log files or debugging. 但是,当文化敏感性对日志文件或调试没有意义时,默认情况下创建区分文化的字符串似乎很愚蠢。

I could use the CurrentCulture to represent numbers and dates in my default ToString() implementations, and also provide ToString(FormatProvider) 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). 我可以使用CurrentCulture来表示我的默认ToString()实现中的数字和日期,还提供ToString(FormatProvider)方法,以便人们可以获得一个对ToString(FormatProvider)不敏感的字符串,以便在日志文件等中使用。但这似乎是愚蠢的,因为它只是强迫开发人员编写更多代码来获取我猜他们想要的文化不敏感的字符串(无论他们是否考虑过它)。

The bottom line is that a string like ObjectName[value=12.234, date=2011-10-01] shouldn't ever appear in a user interface, so why would a programmer ever want it to be localized? 底线是像ObjectName[value=12.234, date=2011-10-01]这样的字符串不应该出现在用户界面中,那么为什么程序员会希望它被本地化?

I've been reading the advice in Framework Design Guidelines on implementing ToString() . 我一直在阅读有关实现ToString()框架设计指南中的建议。 Some of the advice seems somewhat contradictory. 一些建议似乎有点矛盾。 For example: 例如:

I consider ToString 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. 我认为ToString是一种特别危险的方法来提供UI泛型类型,因为它可能会考虑到某些特定的UI而实现,这使得它对其他UI需求毫无用处。 To avoid tempting myself in this way, I prefer to make my ToString 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). 为了避免以这种方式诱惑自己,我更喜欢让我的ToString输出尽可能令人讨厌,以强调唯一应该看到输出的“人类”是“开发人类”(他们自己的亚种)。

and

The most important value of ToString is that the debugger uses it as the default way of displaying the object. ToString最重要的值是调试器将其用作显示对象的默认方式。

don't really seem to fit with: 似乎并不适合:

DO string formatting based on the current thread culture when returning culture-dependent information. DO返回文化相关的信息时,基于当前线程的文化字符串格式化。

and

use the CultureInfo instance returned by a thread's CurrentCulture property to format any numeric or date 使用线程的CurrentCulture属性返回的CultureInfo实例来格式化任何数字或日期

I'm all for following the guidelines, and writing APIs that do what programmers expect. 我全都是为了遵循这些指导原则,编写能够满足程序员期望的API。 But if ToString() is for programmers, then it seems silly to localize it. 但是如果ToString()适用于程序员,那么本地化它似乎很愚蠢。 The C# compiler won't let a programmer write a double literal using a system-dependent decimal separator, so surely ToString() methods written for programmers should behave similarly? C#编译器不会让程序员使用依赖于系统的小数分隔符来编写双字面值,所以为程序员编写的ToString()方法应该表现得类似吗?

What do you think? 你怎么看? When the output from ToString() is not intended for use in a user-interface, should the numbers and dates within it be localized or not? ToString()的输出打算在用户界面中使用时,其中的数字和日期是否应该被本地化?


Update 更新

I did some tests using the DebuggerDisplay attribute, and it looks like, by default, it formats numbers in a culture-insensitive way. 我使用DebuggerDisplay属性进行了一些测试,默认情况下,它看起来像是以文化不敏感的方式对数字进行格式化。

[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();
}

Run that test in the debugger and, when it breaks you can see that the double contained in DoubleHolder is formatted with a . 在调试器中运行该测试,当它中断时,您可以看到DoubleHolder包含的double用a格式化. as a decimal separator. 作为小数点分隔符。

Then close Visual Studio, change your windows Regional Options for Standards and Formats to French, say, and run the test again. 然后关闭Visual Studio,将标准和格式的区域选项更改为法语,然后再次运行测试。 You'll see that doubleString has a , as the decimal separator, but the the debugger still shows the double in DoubleHolder with a . 你会看到doubleString有一个,作为小数分隔符,但调试器仍然在DoubleHolder显示带有的一个double .

I would have liked to test this on a proper French version of Windows, with Visual Studio in French. 我本来希望在适当的法语版Windows上使用法语版的Visual Studio进行测试。 In Visual Studio, if you go to Tools -> Options -> Environment -> International Settings, you can set the Language to "Same as Microsoft Windows". 在Visual Studio中,如果转到“工具” - >“选项” - >“环境” - >“国际设置”,则可以将“语言”设置为“与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. 但是要用法语获取Visual Studio,你需要使用法语版Windows,而我的Windows版本似乎只是英文版。 If anyone has a French Windows, or any other locale that uses , as a decimal separator, it'd be great if you could just check whether the debugger uses . 如果任何人有一个落地窗,或使用任何其他区域,作为小数点分隔,这将会是巨大的,如果你可以只检查调试器是否使用. or , as the decimal separator in formatted doubles. 或者,作为格式化双精度中的小数分隔符。

I'm wondering if Thread.CurrentThread.CurrentUICulture 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. 我想知道Thread.CurrentThread.CurrentUICulture是否可能对Visual Studio调试器的显示方式产生影响,我不确定像上面那样设置它与完全用法语运行Visual Studio相同。

But from the above it does look like the debugger consistently uses . 但从上面看,它确实看起来像调试器一贯使用. 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. 这对我来说意味着文化无关的ToString()方法很好,可能更好,如果它是用于调试目的。

For debugging you want to look into Debugger Display Attributes , not use ToString() . 对于调试,您需要查看调试器显示属性 ,而不是使用ToString()

[DebuggerDisplay("{Name} [date={Date}, value={Value}]")]
public class MyClass {
    // ...
}

As for localization of ToString() , I will pass on the opportunity to comment. 至于ToString()本地化,我将传递评论的机会。

IMO the only two important things here are: IMO这里唯一的两件重要事情是:

  • that you have thought about the intended usage, and are applying culture appropriately 你已经考虑了预期的用途,并正在适当地应用文化
  • that the behaviour is clearly documented 行为清楚地记录在案

If the intended usage of this is logging, then invariant seems fine. 如果预期的用途是记录,那么不变量似乎没问题。 If the intended usage was IDE display, then I'd leave it localized to the current-thread. 如果预期的用法是IDE显示,那么我将它本地化为当前线程。

If unsure, consider adding a ToString(CultureInfo) method, and then the caller can do as they wish. 如果不确定,请考虑添加ToString(CultureInfo)方法,然后调用者可以按照自己的意愿执行操作。 In that scenario I'd assume tw default is the current-culture, and that the logging code should explicitly request invariant (perhaps also via IFormattable). 在那种情况下,我假设tw默认是当前文化,并且日志代码应该明确地请求不变(也许也通过IFormattable)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM