Dlaczego Boolean.ToString wyświetla „True”, a nie „true”

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

Output:
True
False

Czy istnieje uzasadniony powód, dla którego jest to „prawda”, a nie „prawda”? Łamie się podczas pisania XML, ponieważ typ logiczny XML ma małe litery , a także nie jest zgodny z prawdą / fałszem C # (choć nie jest pewien CLS).

Aktualizacja

Oto mój bardzo pospieszny sposób obejścia tego w C # (do użycia z XML)

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

Oczywiście to dodaje 1 dodatkową metodę do stosu, ale wszędzie usuwa ToLowers ().

Chris S.
źródło
1
Pomyślałem, że wspomnę o tym ... Właśnie przeczytałem sprytne obejście, aby przekształcić z postaci szeregowej „True” jako typ logiczny w języku C # na blogu msdn! patrz http://blogs.msdn.com/helloworld/archive/2009/04/03/workaround-to-deserialize-true-false-using-xmlserializer.aspx
Peter
23
Chciałbym zamienić return b.ToString().ToLower();z return b ? "true" : "false";. Czystsze, bardziej wydajne, mniej zależne od metody, która teoretycznie może zależeć od ustawień regionalnych (nawet jeśli nie jest to w obecnych implementacjach).
Jon Hanna
1
Jest to również dość irytujące przy użyciu RestSharp do szeregowania publicznych właściwości obiektu w QueryString w celu wywołania usługi REST WebService. Jeśli w interfejsie API REST rozróżniana jest wielkość liter dla booli (np. Interfejs Google Maps API), powoduje to niepowodzenie wywołania interfejsu API.
Carlos P,
8
„ToString jest główną metodą formatowania w .NET Framework. Konwertuje obiekt na jego reprezentację ciągu, dzięki czemu jest odpowiedni do wyświetlania ”. (Podkreśl moje). Object.ToString nie jest mechanizmem serializacji . :)
Rytmis
1
@awe tak, to takie doświadczenie, które prowadzi mnie do obrony przed teoretycznym ryzykiem, mimo że obecnie tak się nie dzieje.
Jon Hanna

Odpowiedzi:

165

Tylko ludzie z Microsoft mogą naprawdę odpowiedzieć na to pytanie. Chciałbym jednak przedstawić kilka ciekawych faktów na ten temat;)

Po pierwsze, tak mówi MSDN o metodzie Boolean.ToString () :

Zwracana wartość

Wpisz: System.String

TrueString, jeśli wartość tego wystąpienia jest prawdziwa, lub FalseString, jeśli wartość tego wystąpienia jest fałszywa.

Uwagi

Ta metoda zwraca stałe „Prawda” lub „Fałsz”. Zauważ, że w XML rozróżniana jest wielkość liter, a specyfikacja XML rozpoznaje „prawda” i „fałsz” jako prawidłowy zestaw wartości logicznych. Jeśli obiekt String zwrócony przez metodę ToString () ma zostać zapisany w pliku XML, należy najpierw wywołać jego metodę String.ToLower, aby przekonwertować go na małe litery.

Oto zabawny fakt nr 1: w ogóle nie zwraca TrueString ani FalseString. Używa zakodowanych literałów „Prawda” i „Fałsz”. Nie przydałoby ci się, gdyby używał pól, ponieważ są oznaczone jako tylko do odczytu, więc nie można ich zmieniać.

Alternatywna metoda Boolean.ToString (IFormatProvider) jest jeszcze bardziej zabawna :

Uwagi

Parametr dostawcy jest zarezerwowany. Nie uczestniczy w realizacji tej metody. Oznacza to, że metoda Boolean.ToString (IFormatProvider), w przeciwieństwie do większości metod z parametrem dostawcy, nie odzwierciedla ustawień specyficznych dla kultury.

Jakie jest rozwiązanie Zależy, co dokładnie próbujesz zrobić. Cokolwiek to jest, założę się, że będzie to wymagało włamania;)

Vojislav Stojkovic
źródło
2
Popraw mnie, jeśli się mylę, ale nie widzę nic złego w wyjaśnieniu Boolean.ToString(). bool.TrueStringto pole tylko do odczytu, które zawiera zakodowany literał „True” . Dlatego powiedzenie, że zwraca, TrueStringjest tym samym, co powiedzenie, że zwraca na stałe zapisany w nim literał „True” , biorąc pod uwagę, że zwracanie ciągu zawsze zwraca wartość, a nie odwołanie.
Fernando Neira,
21
Obserwowalny wynik jest taki sam. Wdrożenie nie jest.
Vojislav Stojkovic
1
Kompilowanie C # nie zastąpiłoby Boolean.TrueString z „True” w skompilowanych wynikach. Jeśli faktycznie użyli Boolean.TrueString, możesz użyć refleksji, aby zmienić Boolean.TrueString, aby zwrócić małą wersję ... oczywiście, kto wie, co by się zepsuło. Nadal możesz użyć refleksji, aby zastąpić metodę ToString na Boolean, aby zwracała małe litery.
Dewey Vozel
2
@FernandoNeira, jeśli jutro literał na sztywno TrueStringzostanie zmieniony, powiedzmy, na małe „prawda”, metoda bool.ToString()nadal zwróci literał „prawda” w postaci pascal.
Serge
1
Obwiniam Visual Basic, który używa wartości True i False jako swoich dosłownych wartości.
mrcrowl
105

... ponieważ środowisko .NET zostało zaprojektowane do obsługi wielu języków.

System.Boolean (w mscorlib.dll) jest przeznaczony do wewnętrznego użytku przez języki do obsługi logicznego typu danych. C # używa wszystkich małych liter dla swoich słów kluczowych, stąd „bool”, „prawda” i „fałsz”.

VB.NET wykorzystuje jednak standardową obudowę: stąd „Boolean”, „True” i „False”.

Ponieważ języki muszą ze sobą współpracować, nie można uzyskać true.ToString () (C #), co daje inny wynik niż True.ToString () (VB.NET). Projektanci CLR wybrali standardową notację obudowy CLR dla wyniku ToString ().

Reprezentacja ciągu logicznej wartości true jest zdefiniowana jako Boolean.TrueString.

(Podobnie jest w przypadku System.String: C # przedstawia go jako typ „string”).

stusmith
źródło
4
Musieli dostosować VB z wyglądu
Chris S
5
Powiedziałbym, że C # to „dziwny” język. Wszystko, co publiczne w .NET to CamelCase - System.Boolean, True, System.String itp. - to dziedzictwo C # C, które prowadzi do aliasingu łańcucha do ciągu, Boolean do bool, True do true itp. (Chociaż moje osobiste preferencje to wciąż C #).
stusmith
4
Ponadto dobry (dla mnie) powód, dla którego przejście na małe litery jest łatwe, podczas gdy ciężko jest zrobić to CamelCase, szczególnie gdy VB jest używane tak jak powiedział @John Burns. W przeciwnym razie użytkownik VB nie będzie mógł i nigdy nie będzie korzystał z niego ToString()i zmuszony do korzystania z niego If(b, "True", "False"). Więc c # użytkownik taki jak ja musi poświęcić się, aby użyć ToLower():)
CallMeLaNN
2
@MarkLopez Twój komentarz jest niepoprawny, zobacz tutaj: msdn.microsoft.com/en-us/library/c8f5xwh7.aspx . Patrząc na definicję boolowską, okazuje się, że w rzeczywistości jest strukturą, a obie mają te same właściwości.
tsemer
1
Chociaż twoja odpowiedź rzuca trochę światła, nie rozumiem, w jaki sposób „prawda” jest bardziej „standardowa” niż „prawda”. Wygląda na to, że ten drugi jest znacznie bardziej popularny.
Niewielkie
50

W przypadku Xml można użyć metody XmlConvert.ToString .

Bruno Conde
źródło
4
To zdecydowanie najbardziej elegancka metoda. Bez dodatkowego programowania i przy użyciu oficjalnej biblioteki faktycznie utworzonej na potrzeby danych wyjściowych xml.
Nyerguds
25

Prosty kod można przekonwertować na małe litery.

Jednak konwersja „prawdziwej” z powrotem na „prawdziwą” nie jest tak prosta.

true.ToString().ToLower() 

to jest to, czego używam do wyjścia XML.

Jan
źródło
Oprócz odpowiedzi @stusmith, ponieważ do obsługi wielu języków, jest to dobry powód, dla którego Microsoft preferuje wygląd VB ToString()wyniku logicznego .
CallMeLaNN,
@Damieh: właściwie pytanie brzmi „dlaczego”. Wybrana odpowiedź, w przeciwieństwie do tej, jest tak blisko odpowiedzi, jak to tylko możliwe.
Nyerguds,
1
Jeszcze lepiej; ToLowerInvariant().
vulcan raven
3
Za pomocą System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToTitleCase można przekonwertować „true” z powrotem na „true”.
Jenny O'Reilly,
8

Jak to nie jest kompatybilne z C #? Boolean.Parse i Boolean.TryParse nie rozróżniają wielkości liter, a parsowanie odbywa się poprzez porównanie wartości z Boolean.TrueString lub Boolean.FalseString, które są „Prawda” i „Fałsz”.

EDYCJA: Patrząc na metodę Boolean.ToString w reflektorze okazuje się, że ciągi są zakodowane na stałe, więc metoda ToString wygląda następująco:

public override string ToString()
{
    if (!this)
    {
        return "False";
    }
    return "True";
}
Rune Grimstad
źródło
23
Wow ... To chyba jedyny kontekst w języku C #, w którym konstrukcja „if (! This)” jest poprawna!
Tamas Czinege
2
więc dlaczego nie zwraca „fałsz”, o co pytam
Chris S
Co za dziwna rzecz ... Mam na myśli odwrócenie stanu.
nicodemus13
6
@TamasCzinege Rzuciłeś That's probably the only context in C# where the construct "if (!this)" is valid! mi wyzwanie, przegrałeś . gist.github.com/Steinblock/10df18afb948866be1ba - Również dzisiaj jest 200.
rocznica urodzin
Zastanawiasz się, dlaczego tak się nie stało return this ? "True" : "False";? (Kolejny niezwykły przypadek, którego często nie widzisz thisjako ?:warunek, ale tutaj miałby sens).
Darrel Hoffman
7

Znam powód, dla którego już został rozwiązany, ale jeśli chodzi o „niestandardowe” formatowanie boolowskie, mam dwie metody rozszerzenia, bez których nie mogę żyć :-)

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

Użycie jest banalne. Poniższe konwertuje różne wartości bool na ich portugalskie reprezentacje:

string verdadeiro = true.ToString("verdadeiro", "falso");
string falso = false.ToString("verdadeiro", "falso");
bool? v = null;
string nulo = v.ToString("verdadeiro", "falso", "nulo");
Loudenvier
źródło
„Możesz użyć metod rozszerzenia do rozszerzenia klasy lub interfejsu, ale nie w celu ich przesłonięcia. Metoda rozszerzenia o tej samej nazwie i podpisie co interfejs lub metoda klasy nigdy nie będzie wywoływana. W czasie kompilacji metody rozszerzenia mają zawsze niższy priorytet niż metody instancji zdefiniowane w samym typie. ” Czy Twoje rozwiązanie działa? (Może dziedziczona jest
funkcja
1
Myślę, że do mojego poprzedniego komentarza ten podpis niczego nie przesłania.
jwize
@jwize tak, to są nowe podpisy, więc to przeciążenie, a nie przesłonięcie ;-)
Loudenvier
0

Powodem truejest „prawda” z powodu silnej więzi Microsoftu ze standardami XML.

Z Wikipedii : „Extensible Markup Language (XML) to język znaczników, który definiuje zestaw reguł kodowania dokumentów w formacie, który jest zarówno czytelny dla człowieka, jak i maszynowy”.

Czytelny dla człowieka jest subiektywny, ale w oczach XML preferowane jest użycie słowa „Jeden” zamiast liczby „1”. Zauważysz, że dzieje się to za pomocą wyliczeń, ponieważ słowo jest serializowane zamiast jego wartości („FirstOption” zamiast „0” lub „1”).

Podobnie tekst zwykle występuje po CamelCasing . Dlatego zamiast „ciąg” XML preferuje „Ciąg”. Właśnie dlatego Boolean.TrueString ma wartość „True”, a Boolean.FalseString jest domyślnie „False”.

Kody
źródło
7
Zabawne, że boolean XML się zepsuje, jeśli ustawisz go na „Prawda”, a nie „prawda”? - „Zauważ, że w formacie XML rozróżniana jest wielkość liter, a specyfikacja XML rozpoznaje„ prawda ”i„ fałsz ”jako prawidłowy zestaw wartości logicznych”
PandaWood,
-1

Prawdopodobnie wynika to ze starych czasów VB NOT .Net, kiedy bool.ToString produkował wartość True lub False.

cjk
źródło
3
Przed .NET Boolean typu danych w VB (w rzeczywistości wszystkie typy danych) nie miał metod.
Sam Axe
1
W VB6 nadal można konwertować typ boolowski na ciąg znaków (najprostszy sposób przypisania go do zmiennej typu ciąg). Dziwną rzeczą w tym było to, że konwersja była specyficzna dla kultury, więc jeśli językiem kultury na uruchomionym komputerze był norweski, wynikiem były „Sann” i „Usann” zamiast „True” i „False”! Powodowało to często problemy, jeśli ustawienia logiczne były przechowywane w pliku tekstowym i eksportowane do innego środowiska, w którym komputer był skonfigurowany z kulturą angielską (amerykańską).
awe