Переопределение ToString () для отладки и журналов - должна ли строка быть локализована? - PullRequest
8 голосов
/ 05 ноября 2011

Я разрабатываю библиотеку .NET, которая будет использоваться другими разработчиками для веб-приложений и приложений для настольных компьютеров.Я переопределяю ToString() в различных классах, чтобы предоставить информацию для целей отладки и для включения в файлы журнала приложения.

Некоторые из моих классов содержат числа и даты.

Рассмотрим объект, который содержитDateTime с именем date и double с именем value (и, возможно, с другими полями) ... Если я переопределю ToString() этого объекта, я могу захотеть сделать что-то вроде:

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

Но это будет включать в себя результат из date.ToString() и value.ToString(), который даст мне строки, локализованные в соответствии с Thread.CurrentThread.CurrentCulture.

И это, на мой взгляд, неверно.Строки, возвращаемые моими реализациями ToString(), предназначены для отладки и регистрации сообщений, а не для пользовательских интерфейсов.Поэтому я думаю, что возвращение локализованных строк может только сбить с толку.Если в файлах журналов появляется «2,341», разработчику необходимо знать значение CurrentCulture потока, чтобы знать, означает ли оно 2 тысячи 341 или 2 точки 341. Это еще более запутанно с датами - строка типа xx / xx /хххх может быть дд / мм / гггг или мм / дд / гггг.Я не хочу, чтобы мои ToString() методы создавали такую ​​двусмысленность.

Поэтому я склонен сделать мои ToString() методы нечувствительными к культуре, чтобы гарантировать, что все возвращаемые строки согласованы между культурами.Например, внутренне мои ToString() методы будут работать как value.ToString(CultureInfo.InvariantCulture) для форматирования числа.

Однако норма в библиотеках .NET, по-видимому, заключается в использовании CurrentCulture в стандартных реализациях без аргументов ToString().Многие объекты, которые имеют метод ToString(), также имеют метод ToString(IFormatProvider).Как будто разработчики .NET решили, что по умолчанию ToString() должно использоваться для отображения пользовательского интерфейса (локализовано), а отладка и журналы (для которых вам нужно вызвать ToString(CultureInfo.InvariantCulture)) являются вторичными.

Так что, если я реализую свои методы ToString() без учета культурных особенностей, я чувствую, что в какой-то степени буду идти против зерна.Но кажется глупым создавать строки, чувствительные к культуре, по умолчанию, когда чувствительность к культуре не имеет смысла для файлов журналов или отладки.

Я мог бы использовать CurrentCulture для представления чисел и дат в моем значении по умолчанию ToString()реализации, а также предоставляют ToString(FormatProvider) методы, чтобы люди могли получить нечувствительную к культуре строку для использования в файлах журналов и т. д. Но это кажется глупым, так как это просто заставляет разработчиков писать больше кода для получения нечувствительной к культуре строки, которую ядогадываясь, что они захотят (независимо от того, рассматривали ли они это или нет).

Суть в том, что строка типа ObjectName[value=12.234, date=2011-10-01] никогда не должна появляться в пользовательском интерфейсе, так почему программист захочетего нужно локализовать?

Я читал рекомендации в Руководстве по разработке рамок для реализации ToString().Некоторые советы кажутся несколько противоречивыми.Например:

Я считаю ToString особенно опасным способом предоставления универсальных типов пользовательского интерфейса, поскольку он, вероятно, будет реализован с учетом определенного пользовательского интерфейса, что делает его бесполезным для других нужд пользовательского интерфейса.Чтобы не соблазнять себя таким образом, я предпочитаю сделать свой вывод ToString как можно более отвратительным, чтобы подчеркнуть, что единственными «людьми», которые должны когда-либо видеть результат, являются «люди-разработчики» (подвид все их собственные).

и

Наиболее важным значением ToString является то, что отладчик использует его как способ отображения объекта по умолчанию.

donна самом деле не подходит:

DO форматирование строки на основе текущей культуры потоков при возврате информации, зависящей от культуры.

и

использовать экземпляр CultureInfo, возвращаемый свойством потока CurrentCulture, для форматирования любого числа или даты

Я за то, что следую инструкциям и пишу API, которые делают то, что ожидают программисты.Но если ToString() для программистов, то глупо его локализовать.Компилятор C # не позволит программисту написать двойной литерал с использованием системно-зависимого десятичного разделителя, поэтому, конечно, ToString() методы, написанные для программистов, должны вести себя аналогично?

Что вы думаете? Если вывод ToString() равен , а не и предназначен для использования в пользовательском интерфейсе, должны ли быть локализованы числа и даты в нем или нет?


Обновление

Я провел несколько тестов с использованием атрибута 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();
}

Запустите этот тест в отладчике, и, когда он прервется, вы увидите, что double, содержащийся в DoubleHolder, отформатирован с . в качестве десятичного разделителя.

Затем закройте Visual Studio, изменитеДопустим, у вас есть региональные параметры Windows для стандартов и форматов на французский, и снова запустите тест.Вы увидите, что doubleString имеет , в качестве десятичного разделителя, но отладчик по-прежнему показывает double в DoubleHolder с .

Я хотел бы проверить этона правильной французской версии Windows, с Visual Studio на французском.В Visual Studio, если вы идете в Инструменты -> Параметры -> Среда -> Международные настройки, вы можете установить язык "То же, что Microsoft Windows".По умолчанию в моей установке было установлено «Английский».Но чтобы получить Visual Studio на французском, вам нужно иметь Windows на французском, а моя версия Windows кажется только на английском.Если у кого-то есть французская Windows или любая другая локаль, которая использует , в качестве десятичного разделителя, было бы здорово, если бы вы могли просто проверить, использует ли отладчик . или , в качестве десятичного разделителя в отформатированных двойных числах.

Мне интересно, может ли Thread.CurrentThread.CurrentUICulture иметь значение для того, как отладчик Visual Studio показывает вещи, и я не уверен, что установка его, как я делал выше, будет такой же, как и запуск Visual Studio полностью вФранцузский.

Но из вышесказанного выглядит, что отладчик последовательно использует . в качестве десятичного разделителя.Для меня это означает, что независимый от культуры метод ToString () подходит, вероятно, предпочтительнее, если он предназначен для целей отладки.

Ответы [ 2 ]

16 голосов
/ 05 ноября 2011

Для отладки вы хотите посмотреть Атрибуты отображения отладчика , не использовать ToString().

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

Что касается локализации ToString(), я передам возможностькомментарии.

7 голосов
/ 05 ноября 2011

ИМО только две важные вещи здесь:

  • что вы думали о предполагаемом использовании и применяете культуру соответственно
  • что поведение четко задокументировано

Если предполагаемое использование этого - ведение журнала, то инвариант кажется нормальным. Если предполагаемое использование было отображением IDE, то я бы оставил его локализованным для текущего потока.

Если вы не уверены, рассмотрите возможность добавления метода ToString (CultureInfo), и тогда вызывающая сторона может делать все, что пожелает. В этом сценарии я бы предположил, что по умолчанию используется текущая культура, а код регистрации должен явно запрашивать инвариант (возможно, также через IFormattable).

...