Почему Boolean.ToString выводит «True», а не «true»

235
true.ToString() 
false.toString();

Output:
True
False

Есть ли веская причина для того, чтобы это было «Истина», а не «Истина»? Он ломается при написании XML, так как логический тип XML в нижнем регистре , а также не совместим с C / true / false (хотя не уверен насчет CLS).

Обновить

Вот мой очень хакерский способ обойти это в C # (для использования с XML)

internal static string ToXmlString(this bool b)
{
    return b.ToString().ToLower();
}

Конечно, это добавляет еще 1 метод в стек, но удаляет ToLowers () везде.

Крис С
источник
1
Просто подумал, что упомяну это ... Я только что прочитал какой-то умный обходной путь для десериализации "True" как логического типа в C # в блоге msdn! см. http://blogs.msdn.com/helloworld/archive/2009/04/03/workaround-to-deserialize-true-false-using-xmlserializer.aspx
Питер
23
Я бы заменил return b.ToString().ToLower();на return b ? "true" : "false";. Более чистый, более эффективный, менее зависимый от метода, который теоретически может зависеть от локали (даже если в современных реализациях это не так).
Джон Ханна
1
Это также довольно раздражает при использовании RestSharp для сериализации открытых свойств объекта в QueryString для выполнения вызова REST WebService. Если REST API чувствителен к регистру для bools (например, API Google Directions), то это приводит к сбою вызова API.
Карлос П
8
«ToString - основной метод форматирования в .NET Framework. Он преобразует объект в его строковое представление, чтобы он был пригоден для отображения ». (Акцент мой). Object.ToString не является механизмом сериализации . :)
Ритмис
1
@ да, именно такой опыт заставляет меня защититься от теоретического риска, хотя в настоящее время этого не происходит.
Джон Ханна

Ответы:

165

Только люди из Microsoft могут действительно ответить на этот вопрос. Тем не менее, я хотел бы предложить некоторые забавные факты об этом;)

Во-первых, в MSDN говорится о методе Boolean.ToString () :

Возвращаемое значение

Тип: System.String

TrueString, если значение этого экземпляра равно true, или FalseString, если значение этого экземпляра равно false.

замечания

Этот метод возвращает константы «True» или «False». Обратите внимание, что XML чувствителен к регистру, и что спецификация XML распознает «истина» и «ложь» в качестве допустимого набора логических значений. Если объект String, возвращаемый методом ToString (), должен быть записан в файл XML, сначала следует вызвать его метод String.ToLower, чтобы преобразовать его в нижний регистр.

Вот забавный факт # 1: он не возвращает TrueString или FalseString вообще. Он использует жестко закодированные литералы «True» и «False». Не принесет пользы, если будут использованы поля, потому что они помечены как доступные только для чтения, поэтому их не нужно менять.

Альтернативный метод Boolean.ToString (IFormatProvider) еще смешнее:

замечания

Параметр провайдера зарезервирован. Он не участвует в выполнении этого метода. Это означает, что метод Boolean.ToString (IFormatProvider), в отличие от большинства методов с параметром провайдера, не отражает специфичные для культуры параметры.

Какое решение? Зависит от того, что именно вы пытаетесь сделать. Что бы это ни было, держу пари, это потребует взлома;)

Воислав Стойкович
источник
2
Поправьте меня, если я ошибаюсь, но я не вижу ничего плохого в объяснении Boolean.ToString(). bool.TrueStringэто поле только для чтения, которое содержит в буквальном смысле литерал "True" . Следовательно, говорить, что он возвращает, TrueString- это то же самое, что говорить, что он возвращает жестко закодированный литерал «Истина», хранящийся в нем, учитывая, что возвращение строки всегда возвращает значение, а не ссылку.
Фернандо Нейра
21
Наблюдаемый результат тот же. Реализация нет.
Воислав Стойкович
1
Компиляция C # не заменит Boolean.TrueString на «True» в скомпилированных результатах. Если они действительно использовали Boolean.TrueString, то вы могли бы использовать отражение, чтобы изменить Boolean.TrueString, чтобы вернуть строчную версию ... конечно, кто знает, что это сломает. Вы все еще можете использовать отражение, чтобы заменить метод ToString на Boolean, чтобы он возвращал варианты в нижнем регистре.
Дьюи Возел
2
@FernandoNeira, если завтра жестко закодированный литерал TrueStringбудет изменен, скажем, на строчный «true», метод bool.ToString()все равно вернет паскальный регистр «True».
Серж
1
Я виню Visual Basic, который использует True и False в качестве своих буквальных значений.
mrcrowl
105

... потому что среда .NET разработана для поддержки многих языков.

System.Boolean (в mscorlib.dll) предназначен для внутреннего использования языками для поддержки логического типа данных. C # использует все строчные буквы для своих ключевых слов, следовательно, «bool», «true» и «false».

VB.NET, однако, использует стандартный регистр: следовательно, «Boolean», «True» и «False».

Поскольку языки должны работать вместе, у вас не может быть true.ToString () (C #), дающего другой результат для True.ToString () (VB.NET). Разработчики CLR выбрали стандартную запись CLR для результата ToString ().

Строковое представление логического true определено как Boolean.TrueString.

(Есть аналогичный случай с System.String: C # представляет его как тип 'string').

stusmith
источник
4
Они должны были приспособить VB от взглядов вещей
Крис С
5
Я бы сказал, что C # - это «странный» язык. Все общедоступное в .NET - это CamelCase - System.Boolean, True, System.String и т. Д. - это наследие C #, которое приводит к наложению псевдонима String на строку, Boolean на bool, True на true и т. Д. (Хотя мои личные предпочтения все еще C #).
Стусмит
4
Кроме того, веская причина (для меня) заключается в том, что преобразование в нижний регистр легко, в то время как трудно сделать его CamelCase, особенно когда используется VB, как сказал @Jonhn Burns. В противном случае пользователь VB не может и никогда не будет использовать, ToString()и они вынуждены использовать как If(b, "True", "False"). Так что пользователю c # вроде меня нужно пожертвовать, чтобы использовать ToLower():)
CallMeLaNN
2
@MarkLopez Ваш комментарий неверный, см. Здесь: msdn.microsoft.com/en-us/library/c8f5xwh7.aspx . Кроме того, поиск булева определения показывает, что на самом деле это структура, и эти два свойства имеют одинаковые свойства.
Цемер
1
Хотя ваш ответ проливает некоторый свет, я не понимаю, как «True» является более «стандартным», чем «True». Похоже, что последний гораздо популярнее.
Незначительно
50

Для Xml вы можете использовать метод XmlConvert.ToString .

Бруно Конде
источник
4
Это, безусловно, самый элегантный метод. Никакого дополнительного программирования и использования официальной библиотеки, фактически созданной с целью вывода XML.
Nyerguds
25

Это простой код для преобразования в нижний регистр.

Однако не так просто преобразовать «истину» в «истину».

true.ToString().ToLower() 

это то, что я использую для вывода XML.

Джон
источник
В дополнение к ответу @stusmith, потому что для поддержки многих языков это хорошая причина, почему Microsoft предпочитает VB-вид логического ToString()результата.
CallMeLaNN
@Damieh: на самом деле, вопрос «почему». Выбранный ответ, в отличие от этого, на самом деле настолько близок к ответу, насколько это возможно.
Nyerguds
1
Еще лучше; ToLowerInvariant(),
вулкан ворон
3
Вы можете использовать System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToTitleCase, чтобы преобразовать «true» обратно в «True».
Дженни О'Рейли,
8

Как это не совместимо с C #? Boolean.Parse и Boolean.TryParse нечувствительны к регистру, и разбор выполняется путем сравнения значения с Boolean.TrueString или Boolean.FalseString, которые имеют значения «True» и «False».

РЕДАКТИРОВАТЬ: При взгляде на метод Boolean.ToString в отражателе оказывается, что строки жестко закодированы, поэтому метод ToString выглядит следующим образом:

public override string ToString()
{
    if (!this)
    {
        return "False";
    }
    return "True";
}
Руна Гримстад
источник
23
Вау ... Это, наверное, единственный контекст в C #, где допустима конструкция "if (! This)"!
Тамас Чинеге
2
так почему я не возвращаю «ложь» - вот что я спрашиваю
Крис С
Что за странная вещь ... Я имею в виду перевернуть условие.
nicodemus13
6
@TamasCzinege That's probably the only context in C# where the construct "if (!this)" is valid! Вы бросили мне вызов, вы проиграли . gist.github.com/Steinblock/10df18afb948866be1ba - Также сегодня исполняется 200 лет со дня рождения Джорджа Буля
Юрген Стейнблок
Интересно, почему это не было сделано как return this ? "True" : "False";? (Еще один необычный случай, который вы не часто рассматриваете thisкак ?:условие, но здесь это имело бы смысл.)
Даррел Хоффман
7

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

public static class BoolExtensions
{
    public static string ToString(this bool? v, string trueString, string falseString, string nullString="Undefined") {
        return v == null ? nullString : v.Value ? trueString : falseString;
    }
    public static string ToString(this bool v, string trueString, string falseString) {
        return ToString(v, trueString, falseString, null);
    }
}

Использование тривиально. Следующее преобразует различные значения bool в их португальские представления:

string verdadeiro = true.ToString("verdadeiro", "falso");
string falso = false.ToString("verdadeiro", "falso");
bool? v = null;
string nulo = v.ToString("verdadeiro", "falso", "nulo");
Loudenvier
источник
«Вы можете использовать методы расширения для расширения класса или интерфейса, но не для их переопределения. Метод расширения с тем же именем и сигнатурой, что и интерфейс или метод класса, никогда не будет вызываться. Во время компиляции методы расширения всегда имеют более низкий приоритет, чем методы экземпляра, определенные в самом типе. " Работает ли ваше решение? (Может быть ToString () наследуется, поэтому может быть переопределено?)
jwize
1
Я предполагаю, что к моему предыдущему комментарию эта подпись ничего не отменяет.
Jwize
@jwize да, это новые подписи, так что это перегрузка, а не переопределение ;-)
Loudenvier
0

Причина в том, что trueэто правда, из-за сильной связи Microsoft со стандартами XML.

Из Википедии : «Расширяемый язык разметки (XML) - это язык разметки, который определяет набор правил для кодирования документов в формате, который читается человеком и читается машиной».

Человекочитаемый субъективен, но, с точки зрения XML, использование слова «один» вместо числа «1» является предпочтительным. Вы заметите, что это происходит с использованием перечислений, так как слово сериализуется вместо его значения («FirstOption» вместо «0» или «1»).

Точно так же текст обычно следует за CamelCasing . Поэтому вместо «строка» XML предпочитает «строка». Вот почему Boolean.TrueString имеет значение «True», а Boolean.FalseString по умолчанию «False».

Kody
источник
7
Забавно, что XML-логическое значение сломается, если вы установите его в значение «True», а не «true» тогда? - «Обратите внимание, что XML чувствителен к регистру, и что спецификация XML распознает« true »и« false »в качестве допустимого набора логических значений»
PandaWood
-1

Это, вероятно, исходит из старых VB NOT .Net дней, когда bool.ToString производил True или False.

Дальневосточные
источник
3
До .NET логический тип данных в VB (фактически, все типы данных) не имел методов.
Сэм Топор
1
В VB6 вы все еще можете преобразовывать логический тип в строку (самый простой способ присвоить его строковой переменной). Странно было то, что преобразование было на самом деле специфичным для культуры, поэтому, если ваш язык культуры на работающем компьютере был норвежский, результатом были «Sann» и «Usann» вместо «True» и «False»! Это часто вызывало проблемы, если булевы настройки были сохранены в текстовом файле и экспортированы в другую среду, в которой компьютер был настроен на английский (США) язык.
благосклонность