Por que Boolean.ToString produz "True" e não "true"

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

Output:
True
False

Existe uma razão válida para ser "verdadeiro" e não "verdadeiro"? Ele quebra ao escrever XML, pois o tipo booleano do XML é minúsculo e também não é compatível com true / false do C # (embora não tenha certeza sobre o CLS).

Atualizar

Aqui está minha maneira muito hacky de contornar isso em C # (para uso com XML)

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

É claro que isso adiciona mais 1 método à pilha, mas remove ToLowers () em todos os lugares.

Chris S
fonte
1
Só pensei em mencionar isso ... Acabei de ler uma solução alternativa inteligente para desserializar "True" como um tipo booleano em C # em um blog msdn! consulte http://blogs.msdn.com/helloworld/archive/2009/04/03/workaround-to-deserialize-true-false-using-xmlserializer.aspx
Peter
23
Eu substituiria return b.ToString().ToLower();por return b ? "true" : "false";. Mais limpo, mais eficiente, menos dependente de um método que teoricamente poderia depender da localidade (mesmo que não nas implementações atuais).
Jon Hanna
1
Isso também é bastante irritante ao usar o RestSharp para serializar as propriedades públicas de um objeto em um QueryString para fazer uma chamada REST WebService. Se a API REST faz distinção entre maiúsculas e minúsculas para bools (por exemplo, a API do Google Directions), isso causa uma falha na chamada da API.
Carlos P
8
"ToString é o principal método de formatação no .NET Framework. Ele converte um objeto em sua representação de string para que seja adequado para exibição ." (Ênfase minha). Object.ToString não é um mecanismo de serialização . :)
Rytmis
1
@ sim, esse é o tipo de experiência que me leva a me proteger contra o risco teórico, mesmo que isso não aconteça no momento.
Jon Hanna

Respostas:

165

Somente pessoas da Microsoft podem realmente responder a essa pergunta. No entanto, gostaria de oferecer alguns fatos interessantes sobre o assunto;)

Primeiro, é o que diz no MSDN sobre o método Boolean.ToString () :

Valor de retorno

Tipo: System.String

TrueString se o valor desta instância for verdadeiro ou FalseString se o valor dessa instância for falso.

Observações

Este método retorna as constantes "Verdadeiro" ou "Falso". Observe que o XML diferencia maiúsculas de minúsculas e que a especificação XML reconhece "true" e "false" como o conjunto válido de valores booleanos. Se o objeto String retornado pelo método ToString () for gravado em um arquivo XML, seu método String.ToLower deverá ser chamado primeiro para convertê-lo em minúsculas.

Aí vem o fato divertido # 1: ele não retorna TrueString ou FalseString. Ele usa literais codificados como "Verdadeiro" e "Falso". Não faria nenhum bem se eles usassem os campos, porque eles são marcados como somente leitura, para que não haja como alterá-los.

O método alternativo, Boolean.ToString (IFormatProvider) é ainda mais engraçado:

Observações

O parâmetro provider está reservado. Não participa da execução deste método. Isso significa que o método Boolean.ToString (IFormatProvider), diferente da maioria dos métodos com um parâmetro de provedor, não reflete as configurações específicas da cultura.

Qual a solução? Depende do que exatamente você está tentando fazer. Seja o que for, aposto que será necessário um hack;)

Vojislav Stojkovic
fonte
2
Corrija-me se estiver errado, mas não vejo nada de errado com a explicação para Boolean.ToString(). bool.TrueStringé um campo somente leitura que contém o literal codificado como "True" . Portanto, dizer que ele retorna TrueStringé o mesmo que dizer que ele retorna o literal codificado "True" armazenado nele, já que o retorno de uma string sempre retorna o valor e não uma referência.
Fernando Neira
21
O resultado observável é o mesmo. A implementação não é.
Vojislav Stojkovic
1
Compilar o C # não substitui o Boolean.TrueString por "True" nos resultados compilados. Se eles realmente fizessem uso do Boolean.TrueString, você poderia usar a reflexão para alterar o Boolean.TrueString para retornar uma versão em minúscula ... é claro quem sabe o que isso iria quebrar. Você ainda pode usar a reflexão para substituir o método ToString no Boolean, para que ele retorne as variantes em minúsculas.
Dewey Vozel
2
@FernandoNeira, se amanhã o literal codificado TrueStringfor alterado, digamos, para minúsculas "true", o método bool.ToString()ainda retornará o caso pascal "True" literal.
Serge
1
Eu culpo o Visual Basic, que usa True e False como seus valores literais.
Mrcrowl #
105

... porque o ambiente .NET foi projetado para suportar vários idiomas.

O System.Boolean (em mscorlib.dll) foi projetado para ser usado internamente pelos idiomas para oferecer suporte a um tipo de dados booleano. C # usa todas as letras minúsculas para suas palavras-chave, portanto 'bool', 'true' e 'false'.

No entanto, o VB.NET usa caixa padrão: daí 'Boolean', 'True' e 'False'.

Como os idiomas precisam trabalhar juntos, você não poderia ter true.ToString () (C #), dando um resultado diferente a True.ToString () (VB.NET). Os designers do CLR escolheram a notação de caixa padrão do CLR para o resultado ToString ().

A representação em cadeia do valor booleano true é definida como Boolean.TrueString.

(Existe um caso semelhante com System.String: C # o apresenta como o tipo 'string').

stusmith
fonte
4
Eles tiveram que acomodar VB partir da aparência das coisas
Chris S
5
Eu diria que C # é a linguagem "ímpar". Tudo o que é público no .NET é CamelCase - System.Boolean, True, System.String, etc. - é o legado C do C # que leva ao alias de String para string, Booleano para booleano, True para true, etc. (Embora minha preferência pessoal seja ainda c #).
stusmith
4
Além disso, o bom motivo (para mim) é converter para letras minúsculas, é fácil, embora seja difícil transformá-lo no CamelCase, especialmente quando o VB é usado exatamente como o @John Burns disse. Caso contrário, o usuário do VB não pode e nunca usará o ToString()e forçou a usar como If(b, "True", "False"). Então c # usuário como eu precisa sacrificar para uso ToLower():)
CallMeLaNN
2
@MarkLopez Seu comentário está incorreto, consulte aqui: msdn.microsoft.com/en-us/library/c8f5xwh7.aspx . Além disso, procurar a definição booleana revela que é de fato uma estrutura, e as duas têm as mesmas propriedades.
Tsemer
1
Enquanto sua resposta lança alguma luz, não entendo como "Verdadeiro" é mais "padrão" do que "verdadeiro". Parece que o último é muito mais popular.
Leve
50

Para o Xml, você pode usar o método XmlConvert.ToString .

bruno conde
fonte
4
Este parece, de longe, o método mais elegante. Nenhuma programação extra e o uso de uma biblioteca oficial realmente criada para fins de saída xml.
Nyerguds
25

É um código simples converter tudo isso para minúsculas.

Não é tão simples converter "true" de volta para "True", no entanto.

true.ToString().ToLower() 

é o que eu uso para a saída xml.

John
fonte
Além da resposta do @stusmith, porque para oferecer suporte a vários idiomas, esse é um bom motivo para a Microsoft preferir a aparência VB do ToString()resultado booleano .
CallMeLaNN
@ Damieh: na verdade, a pergunta é "por que". A resposta selecionada, ao contrário desta, na verdade chega o mais perto possível de responder a ela.
Nyerguds
1
Melhor ainda; ToLowerInvariant().
rc vulcan raven
3
Você pode usar System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToTitleCase para converter "true" novamente em "True".
Jenny O'Reilly
8

Como isso não é compatível com C #? Boolean.Parse e Boolean.TryParse não fazem distinção entre maiúsculas e minúsculas e a análise é feita comparando o valor com Boolean.TrueString ou Boolean.FalseString que são "True" e "False".

EDIT: Ao olhar para o método Boolean.ToString no refletor, verifica-se que as seqüências de caracteres são codificadas permanentemente, portanto o método ToString é o seguinte:

public override string ToString()
{
    if (!this)
    {
        return "False";
    }
    return "True";
}
Rune Grimstad
fonte
23
Uau ... Esse é provavelmente o único contexto em C # em que a construção "if (! This)" é válida!
Tamas Czinege 29/01/09
2
então por que não é ele voltar "false" é o que eu estou pedindo
Chris S
Que coisa mais estranha a se fazer ... quero dizer, inverter a condição.
precisa saber é o seguinte
6
@TamasCzinege That's probably the only context in C# where the construct "if (!this)" is valid! Você me desafiou, você solta. gist.github.com/Steinblock/10df18afb948866be1ba - Também hoje é o birtday 200 de George Boole
Jürgen Steinblock
Gostaria de saber por que isso não foi feito como return this ? "True" : "False";? (Outro caso incomum como você não vê frequentemente thiscomo uma ?:condição, mas aqui não faria sentido.)
Darrel Hoffman
7

Sei que a razão pela qual ela é desse jeito já foi abordada, mas quando se trata de formatação booleana "personalizada", tenho dois métodos de extensão que não podem mais viver sem :-)

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

O uso é trivial. A seguir, converte vários valores bool para suas representações em português:

string verdadeiro = true.ToString("verdadeiro", "falso");
string falso = false.ToString("verdadeiro", "falso");
bool? v = null;
string nulo = v.ToString("verdadeiro", "falso", "nulo");
Loudenvier
fonte
"Você pode usar métodos de extensão para estender uma classe ou interface, mas não para substituí-los. Um método de extensão com o mesmo nome e assinatura que um método de interface ou classe nunca será chamado. No momento da compilação, os métodos de extensão sempre têm prioridade mais baixa do que métodos de instância definidos no próprio tipo ". O seu trabalho solução (talvez toString () é herdada, portanto, pode ser anulado?)?
jwize
1
Acho que no meu comentário anterior essa assinatura não está substituindo nada.
jwize
@jwize sim, estes são novas assinaturas, por isso é uma sobrecarga não uma substituição ;-)
Loudenvier
0

O motivo trueé "Verdadeiro", devido ao forte vínculo da Microsoft com os padrões XML.

Da Wikipedia : "Extensible Markup Language (XML) é uma linguagem de marcação que define um conjunto de regras para codificar documentos em um formato que é legível por humanos e legível por máquina".

Legível por humanos é subjetivo, mas aos olhos do XML, é preferível usar a palavra "Um" no lugar de um número "1". Você notará que isso acontece usando enumerações, pois a palavra é serializada em vez de seu valor ("FirstOption" em vez de "0" ou "1").

Da mesma forma, o texto geralmente segue o CamelCasing . Portanto, em vez de "string", o XML prefere "String". É por isso que Boolean.TrueString é "True" e Boolean.FalseString é "False" por padrão.

Kody
fonte
7
Engraçado que o booleano XML será quebrado se você o definir como "True" e não "true", então? - "Note-se que XML é sensível a maiúsculas e que a especificação XML reconhece 'verdadeiro' e 'falso' como o conjunto válido de valores booleanos"
PandaWood
-1

Provavelmente isso remete aos velhos tempos do VB NOT .Net quando o bool.ToString produziu True ou False.

cjk
fonte
3
Antes do .NET, o tipo de dados booleano no VB (na verdade, todos os tipos de dados) não tinha métodos.
Sam Sam
1
No VB6, você ainda pode converter o tipo booleano em string (a maneira mais simples de atribuí-lo a uma variável String). O mais estranho disso é que a conversão era realmente específica da cultura; portanto, se o idioma da sua cultura no computador em execução era norueguês, o resultado foi "Sann" e "Usann" em vez de "Verdadeiro" e "Falso"! Isso geralmente causava problemas se as configurações booleanas eram armazenadas em um arquivo de texto e exportadas para um ambiente diferente em que o computador estava configurado com a cultura em inglês (EUA).
temor