Dlaczego / kiedy należałoby zastąpić ToString?

103

Studiuję C # i zastanawiam się, jaki ToStringmoże być cel i korzyść zastąpienia , jak pokazano w poniższym przykładzie.

Czy można to zrobić w prostszy sposób, używając wspólnej metody bez nadpisywania?

public string GetToStringItemsHeadings
{
    get { return string.Format("{0,-20} {1, -20}", "Office Email", "Private Email"); }
}


public override string ToString()
{
    string strOut = string.Format("{0,-20} {1, -20}", m_work, m_personal);
    return strOut;
}
3D-kreativ
źródło
4
Zależy, czy rzeczywiście chcesz go używać do wyświetlania obiektu w interfejsie użytkownika w dowolnym miejscu, w przeciwnym razie zwykle służy to tylko do debugowania - zobaczysz wynik ToString w oknie obserwacyjnym VS. (Ale możesz to również osiągnąć za pomocą atrybutów w klasie.) Biorąc pod uwagę, że masz nagłówki i dane wyjściowe, wygląda na to, że ten program używa ich do zrzucenia obiektu za pomocą Console.WriteLine(obj.GetToStringItemsHeadings); Console.WriteLine(obj);lub czegoś podobnego.
Rup
2
Naprawdę nie rozumiem pytania. Czy można to zrobić inaczej? Tak. Ale dlaczego chcesz to zrobić inaczej.
Konrad Rudolph
5
Naprawdę GetToStringConsole.WriteLine(obj.ItemHeadings)
pominęłabym
i zmień właściwość ItemHeadings na statyczną, ponieważ nie wymaga ona żadnego „this”.
eFloh
Możesz sprawdzić to pytanie: stackoverflow.com/questions/7906828/oo-design-advice-tostring
Yuri Ghensev

Odpowiedzi:

127
  • Czy musisz nadpisać ToString? Nie.

  • Czy możesz uzyskać ciąg reprezentujący swój obiekt w inny sposób? Tak.

Ale używając ToString, używasz metody, która jest wspólna dla wszystkich obiektów i dlatego inne klasy wiedzą o tej metodzie. Na przykład, ilekroć platforma .NET chce przekonwertować obiekt na reprezentację w postaci ciągu, ToStringjest głównym kandydatem (są inne, jeśli chcesz zapewnić bardziej rozbudowane opcje formatowania).

Konkretnie,

Console.WriteLine(yourObject);

wywoływał yourObject.ToString().

Konrad Rudolph
źródło
13
Tak. Jest to również bardzo przydatne w programowaniu MVC lub ASP.Net, gdzie @yourObjecti <%=yourObject%>będzie to „ToString-ed”.
Ben Lesh
4
Również podczas
zapełniania
3
Uważaj na takie praktyki. Prawdziwa historia: uczeń zastąpił ToString metodą, która oprócz zwrócenia ciągu znaków, zmieniła dane. Debugował program, ale gdy program znajdował się w punkcie przerwania, wartość ciągle się zmieniała. Najwyraźniej - za każdym razem, gdy sprawdzał wartość ToString był wykonywany - więc wartość zmieniała się, mimo że program nie był uruchomiony.
JNF
3
@JNF Co to jest „taka praktyka”? ToStringnie powinien w rzeczywistości zmieniać stanu obiektu. Ale to nie jest to, za czym się opowiadałem.
Konrad Rudolph
8
@JNF Nie akceptuję tego. ToStringjest przeznaczona do być pominięte. Kropka. Zastrzeżenie tego stwierdzenia nie jest produktywne. Jeśli zrobisz to źle - twoja wina. W rzeczywistości twój uczeń naruszył punkt 4 na oficjalnej liście wytycznych dotyczących unieważniania, ToStringktóra została zamieszczona w odpowiedzi Davida Andersona.
Konrad Rudolph
129

Po prostu dam ci odpowiedź prosto z wytycznych dotyczących projektowania ram z serii .NET Development.

UNIKAJ rzucania wyjątków zToString

ROZWAŻ zwracanie unikatowego ciągu powiązanego z instancją.

NALEŻY ROZWAŻYĆ, że dane wyjściowe ToStringsą poprawnymi danymi wejściowymi dla wszystkich metod analizy tego typu.

DO upewnić się, że ToStringnie ma żadnych dostrzegalnych skutków ubocznych.

NALEŻY zgłaszać informacje wrażliwe z punktu widzenia bezpieczeństwa poprzez zastąpienie ToStringtylko po zażądaniu odpowiedniego pozwolenia. Jeśli żądanie uprawnień nie powiedzie się, zwróć ciąg wykluczający informacje wrażliwe na bezpieczeństwo.

Object.ToStringSposób ma być stosowana do celów wyświetlania i diagnostyki. Domyślna implementacja po prostu udostępnia nazwę typu obiektu. Domyślna implementacja nie jest zbyt przydatna i zaleca się przesłonięcie metody.

NALEŻY przesłonić, ToStringgdy można zwrócić interesujący ciąg czytelny dla człowieka. Domyślna implementacja nie jest zbyt przydatna, a implementacja niestandardowa prawie zawsze może zapewnić większą wartość.

WOLNO przyjazną nazwę zamiast unikalnego, ale nieczytelnego identyfikatora.

Warto również wspomnieć, ponieważ Chris Sells wyjaśnia również w wytycznych, co ToStringjest często niebezpieczne dla interfejsów użytkownika. Generalnie moja praktyczna zasada polega na ujawnieniu właściwości, która będzie używana do wiązania informacji z interfejsem użytkownika, i pozostawieniu ToStringnadpisania w celu wyświetlania informacji diagnostycznych deweloperowi. Możesz również ozdobić swój typ DebuggerDisplayAttribute.

DO starają się zachować ciąg zwrócony z ToStringkrótka. Debugger używa ToStringdo uzyskania tekstowej reprezentacji obiektu, który ma być pokazany programiście. Jeśli ciąg jest dłuższy niż może wyświetlić debuger, proces debugowania jest utrudniony.

Wykonaj formatowanie ciągów na podstawie bieżącej kultury wątku podczas zwracania informacji zależnych od kultury.

Zapewnij przeciążenie ToString(string format)lub zaimplementuj IFormattable, jeśli ciąg zwracany z ToStringjest wrażliwy na kulturę lub istnieją różne sposoby formatowania ciągu. Na przykład DateTimezapewnia przeciążenie i implementuje IFormattable.

NIE zwracaj pustego ciągu lub wartości null zToString

Przysięgam na te wytyczne i powinieneś to zrobić. Nie mogę powiedzieć, jak poprawił się mój kod tylko dzięki tej jednej wytycznej dotyczącej ToString. To samo dotyczy rzeczy takich jak IEquatable(Of T)i IComparable(Of T). Te rzeczy sprawiają, że Twój kod jest bardzo funkcjonalny i nie będziesz żałować poświęcenia dodatkowego czasu na jego implementację.

Osobiście nigdy nie używałem ToString zbyt wiele w interfejsach użytkownika, zawsze ujawniałem jakąś właściwość lub jakąś metodę. Większość czasu powinieneś używać ToStringdo debugowania i celów programistycznych. Służy do wyświetlania ważnych informacji diagnostycznych.

David Anderson
źródło
6
Dobra odpowiedź. Czy są to wytyczne, do których odsyłasz msdn.microsoft.com/en-us/library/ms229042.aspx ?
Jodrell
2
@Jodrell Wydaje mi się, że pochodzi z wytycznych dotyczących projektowania ram
Jim Schubert,
6
Potrzebne lepsze źródło.
Ben Voigt,
13
Nie wiedziałem, że SO zamienia się w Wikipedię.
David Anderson,
14
Nie jest, ale kiedy cytujesz wytyczne, podanie źródła jest niezaprzeczalnym plusem.
Falanwe
39

Zastępowanie ToString()umożliwia nadanie klasie użytecznej reprezentacji ciągu w postaci czytelnej dla człowieka.

Oznacza to, że wynik może ujawnić przydatne informacje o Twojej klasie. Na przykład, jeśli masz klasę Person, możesz wybrać ToString()wyświetlanie identyfikatora osoby, jej imienia, nazwiska itp. Jest to niezwykle przydatne podczas debugowania lub logowania.

Odnosząc się do twojego przykładu - trudno powiedzieć, czy twoje przesłonięcie jest przydatne, nie wiedząc, czym jest ta klasa - ale sama implementacja jest w porządku.

Rob Levine
źródło
13

Zawsze jest to właściwe, ale dokładnie rozważ intencje stojące za tym, co wyświetlasz

Lepszym pytaniem byłoby zadać:

Dlaczego jeden miałby zastąpić ToString ()?

ToString () jest oknem do stanu obiektu. Nacisk na państwo jako wymóg. Zdecydowanie języki OOP, takie jak Java / C #, nadużywają modelu OOP, hermetyzując wszystko w klasie. Wyobraź sobie, że kodujesz w języku, który nie jest zgodny z silnym modelem OOP; zastanów się, czy użyjesz klasy czy funkcji. Jeśli użyjesz go jako funkcji (tj. Czasownika, akcji), a stan wewnętrzny jest utrzymywany tylko tymczasowo między wejściem / wyjściem, ToString () nie doda wartości.

Jak wspominali inni, ważne jest, aby wziąć pod uwagę to , co wyprowadzasz za pomocą ToString (), ponieważ może być używane przez debuger lub inne systemy.

Lubię wyobrażać sobie metodę ToString jako parametr --help obiektu. Powinien być krótki, czytelny, oczywisty i łatwy do wyświetlenia. Powinien pokazywać to, czym obiekt nie jest tym, co robi . Mając to wszystko na uwadze, rozważmy ...

Przykład zastosowania - analizowanie pakietu TCP:

Nie jest to przechwytywanie sieci tylko na poziomie aplikacji, ale coś bardziej mięsistego, jak przechwytywanie PCAP.

Chcesz przeciążać ToString () tylko dla warstwy TCP, aby móc drukować dane na konsoli. Co by to zawierało? Możesz oszaleć i przeanalizować wszystkie szczegóły TCP (tj. TCP jest złożony) ...

Który obejmuje:

  • Port źródłowy
  • Port docelowy
  • Numer sekwencji
  • Numer potwierdzenia
  • Przesunięcie danych
  • Flagi
  • Przesunięcie okna
  • Suma kontrolna
  • Pilny wskaźnik
  • Opcje ( nawet nie zamierzam tam iść)

Ale czy chciałbyś otrzymać wszystkie te śmieci, gdybyś wywoływał TCP.ToString () na 100 pakietach? Oczywiście, że nie, byłoby to przeładowanie informacjami. Łatwy i oczywisty wybór jest też najbardziej rozsądny ...

Pokaż, czego ludzie oczekiwaliby zobaczyć:

  • Port źródłowy
  • Port docelowy

Wolę rozsądne wyjście, które jest łatwe do przeanalizowania przez ludzi, ale YMMV .

TCP:[destination:000, source:000]

Nic skomplikowanego, dane wyjściowe nie są przeznaczone do analizowania przez maszyny (tj. Chyba, że ​​ludzie nadużywają twojego kodu), zamierzonym celem jest czytelność dla ludzi.

Ale co z resztą tych soczystych informacji, o których mówiłem wcześniej, czy to też nie jest przydatne? Dojdę do tego, ale najpierw ...


ToString () to jedna z najbardziej wartościowych i rzadko wykorzystywanych metod wszechczasów

Z dwóch powodów:

  1. Ludzie nie rozumieją, do czego służy ToString ()
  2. W podstawowej klasie „Object” brakuje innej, równie ważnej metody łańcuchowej.

Powód 1 - nie nadużywaj użyteczności ToString ():

Wiele osób używa ToString () do ściągnięcia prostej reprezentacji obiektu w postaci ciągu. Podręcznik języka C # stwierdza nawet:

ToString to główna metoda formatowania w .NET Framework. Konwertuje obiekt na jego reprezentację w postaci ciągu, aby nadawał się do wyświetlania.

Wyświetl, a nie dalsze przetwarzanie. To nie znaczy, weź moją ładną reprezentację łańcuchową pakietu TCP powyżej i ściągnij port źródłowy za pomocą regex :: cringe ::.

Prawy sposób robić rzeczy jest ToString call () bezpośrednio na posesji SourcePort (który przy okazji jest ushort tak toString () powinna być już dostępna).

Jeśli potrzebujesz czegoś bardziej niezawodnego do spakowania stanu złożonego obiektu do analizowania maszynowego, lepiej będzie, używając strategii serializacji strukturalnej.

Na szczęście takie strategie są bardzo powszechne:

  • ISerializable (C #)
  • Pickle (Python)
  • JSON (JavaScript lub dowolny język, który go implementuje)
  • MYDŁO
  • itp...

Uwaga: Chyba że używasz PHP, ponieważ, herp-derp, jest do tego funkcja :: snicker ::

Powód 2 - ToString () nie wystarczy:

Nie widziałem jeszcze języka, który implementowałby to u podstaw, ale widziałem i stosowałem różne odmiany tego podejścia na wolności.

Niektóre z nich obejmują:

  • ToVerboseString ()
  • ToString (verbose = true)

Zasadniczo ten włochaty bałagan w stanie pakietu TCP powinien być opisany dla czytelności dla ludzi. Aby uniknąć `` bicia martwego konia '' mówiącego o TCP, `` wskażę palcem '' przypadek nr 1, w którym myślę, że ToString () i ToVerboseString () są niedostatecznie wykorzystywane ...

Przykład zastosowania - tablice:

Jeśli używasz głównie jednego języka, prawdopodobnie czujesz się komfortowo z jego podejściem. Dla ludzi takich jak ja, którzy przeskakują między różnymi językami, liczba różnych podejść może być irytująca.

To znaczy, ile razy mnie to irytowało, przekracza sumę wszystkich palców każdego hinduskiego boga razem wziętych.

Istnieją różne przypadki, w których języki używają wspólnych hacki i mało , że się go w prawo . Niektórzy wymagają ponownego wynalezienia koła, niektórzy robią płytkie wysypisko, inni robią głębokie wysypisko, żaden z nich nie działa tak, jak bym chciał ...

Proszę o bardzo proste podejście:

print(array.ToString());

Dane wyjściowe: „Tablica [x]” lub „Tablica [x] [y]”

Gdzie x to liczba elementów w pierwszym wymiarze, a y to liczba elementów w drugim wymiarze lub pewna wartość wskazująca, że ​​drugi wymiar jest postrzępiony (może zakres min / max?).

I:

print(array.ToVerboseString());

Całość ładnie drukuje, ponieważ cenię ładne rzeczy.

Miejmy nadzieję, że rzuca to trochę światła na temat, który irytował mnie od dawna. Przynajmniej posypałem małą przynętę na trolle dla PHPersów, aby zignorowali tę odpowiedź.

Evan Plaice
źródło
Napisałeś: „Nie widziałem jeszcze języka, który implementowałby to u podstaw”. Wydaje mi się, że Python jest do tego bardzo bliski; np. drukowanie tablicy daje zwięzłe wszystkie jej dane. To jedna rzecz, której brakuje mi w C # / Javie, chociaż podoba mi się ich rygorystyczność. A kiedy trzeba odrobinę wyjść poza ToString (), dobrze byłoby mieć coś w rodzaju składni list złożonych w Pythonie; Myślę, że string.Join () jest podobny, choć mniej elastyczny.
Jon Coombs,
1
@JCoombs Nie zgadzam się, rozumienie jest świetne. Przemieszczanie się po strukturach danych w Pythonie za pomocą zrozumień znacznie ułatwia życie, ale takie podejście nadal wymaga gruntownej znajomości wewnętrznej struktury obiektu. Coś, co nie zawsze jest oczywiste w przypadku klas, które zostały zaimportowane z zewnętrznej biblioteki. Dobrą praktyką dla autorów biblioteki jest przesłonięcie ToString () i zapewnienie użytecznej reprezentacji czytelnej dla człowieka, ale dobrze byłoby mieć również ogólną metodę zrzutu, która wyprowadza strukturę obiektu w ogólnym formacie czytelnym dla człowieka (np. JSON).
Evan Plaice
Doskonała uwaga. Więc zamiast pokazywać tylko po prostu typ typeof, może automatycznie serializować do czegoś takiego jak JSON. (Do tej pory widziałem tylko obiekty .NET serializowane do XML, ale jestem nowy w .NET). (Np. Spodziewaj się, że uda się go zdeserializować.)
Jon Coombs
1
@JCoombs Tak, na poziomie funkcjonalnym JSON i XML służą temu samemu celowi. Wiele osób używa ToString jako danych wyjściowych do odczytu maszynowego; czy to jest złe, czy nie, jest dyskusyjne. Moim największym atutem jest - często czasami - wyświetlanie stanu obiektu w formacie czytelnym dla człowieka. Implementacja ToString () jest często niedostatecznie wykorzystywana, a odczyt stanu obiektu poza listami kontrolnymi debuggera jest uciążliwy. Reprezentacje serializowane są dobre jako kopia zapasowa do wyświetlania całego stanu obiektów, ale lepszą opcją są lepsze implementacje ToString.
Evan Plaice,
Jeśli ToString()jest przeznaczony do debugowania, to dlaczego jest to jedyny sposób na wyodrębnienie całego tekstu z StringBuilder - ważna funkcja?
Dan W
9

Tak naprawdę chodzi przede wszystkim o dobrą praktykę.

ToString()jest używany w wielu miejscach do zwracania łańcucha reprezentującego obiekt, zazwyczaj do spożycia przez człowieka. Często ten sam ciąg może być użyty do ponownego uwodnienia obiektu (pomyśl o nim intlub DateTimena przykład), ale nie zawsze jest to dane (na przykład drzewo może mieć użyteczną reprezentację ciągu, która po prostu wyświetla Licznik, ale wyraźnie nie możesz użyć żeby go odbudować).

W szczególności debugger użyje tego do wyświetlenia zmiennej w oknach obserwacyjnych, oknach bezpośrednich itp., Dlatego ToStringjest nieoceniony przy debugowaniu.

Ogólnie rzecz biorąc, taki typ często będzie miał jawnego członka, który również zwraca ciąg. Na przykład para szerokość / długość może mieć, na przykład, ToDecimalDegreeszwrot "-10, 50", ale może również mieć ToDegreesMinutesSeconds, ponieważ jest to inny format dla pary szerokość / długość. Ten sam typ może następnie zastąpić ToStringjednym z nich, aby zapewnić `` domyślne '' dla rzeczy takich jak debugowanie, a nawet potencjalnie dla rzeczy takich jak renderowanie stron internetowych (na przykład @konstrukcja w Razor zapisuje ToString()wynik wyrażenia niebędącego ciągiem do strumień wyjściowy).

Andras Zoltan
źródło
6

object.ToString()konwertuje obiekt na jego reprezentację w postaci łańcucha. Jeśli chcesz zmienić to, co jest zwracane, gdy użytkownik wywołuje ToString()klasę, którą utworzyłeś, musisz nadpisać ToString()w tej klasie.

Robbie
źródło
6

Chociaż myślę, że najbardziej przydatne informacje zostały już podane, dodam moje dwa centy:

  • ToString()ma zostać zastąpiony. Jego domyślna implementacja zwraca nazwę typu, która, choć czasami może być przydatna (szczególnie podczas pracy z wieloma obiektami), w większości przypadków nie wystarcza.

  • Pamiętaj, że do celów debugowania możesz polegać DebuggerDisplayAttribute. Więcej na ten temat przeczytasz tutaj .

  • Z reguły na POCO zawsze możesz zmienić ToString(). POCO to ustrukturyzowana reprezentacja danych, która zwykle może stać się ciągiem.

  • Zaprojektuj ToString tak, aby był tekstową reprezentacją twojego obiektu. Może jego główne pola i dane, może opis, ile elementów jest w kolekcji itp.

  • Zawsze staraj się dopasować ten ciąg do jednej linii i miej tylko istotne informacje. Jeśli masz Personklasę z właściwościami Nazwa, Adres, Numer itp., Zwróć tylko główne dane (Nazwij numer identyfikacyjny).

  • Uważaj, aby nie zastąpić dobrej implementacji ToString(). Niektóre klasy frameworków już implementują ToString(). Zastępowanie tej domyślnej implementacji jest złą rzeczą: ludzie będą oczekiwać określonego wyniku ToString()i otrzymają inny.

Nie bój się używać ToString(). Jedyne, na co bym uważał, to zwracanie poufnych informacji. Poza tym ryzyko jest minimalne. Oczywiście, jak niektórzy zauważyli, inne klasy będą używać Twojego ToString, gdy sięgną po informacje. Ale do diabła, kiedy zwrócenie nazwy typu będzie uważane za lepsze niż uzyskanie niektórych rzeczywistych informacji?

Bruno Brant
źródło
5

Jeśli tego nie ToStringzrobisz, otrzymasz implementację klas bazowych, która Objectjest tylko krótką nazwą typu klasy.

Jeśli chcesz jakiejś innej, bardziej znaczącej lub użytecznej implementacji, ToStringzastąp ją.


Może to być przydatne, gdy używasz listy Twojego typu jako źródła danych dla a, ListBoxponieważ ToStringzostanie automatycznie wyświetlony.

Inna sytuacja ma miejsce, gdy chcesz przekazać swój typ, do String.Formatktórego wywołuje się w ToStringcelu uzyskania reprezentacji twojego typu.

Jodrell
źródło
4

Coś, o czym nikt jeszcze nie wspomniał: zastępując ToString(), możesz również rozważyć wdrożenie, IFormattableaby wykonać następujące czynności:

 public override ToString() {
   return string.Format("{0,-20} {1, -20}", m_work, m_personal);
 }

 public ToString(string formatter) {
   string formattedEmail = this.ToString();
   switch (formatter.ToLower()) {
     case "w":
       formattedEmail = m_Work;
       break;
     case "p":
       formattedEmail = m_Personal;
       break;
     case "hw":
       formattedEmail = string.Format("mailto:{0}", m_Work);
       break;
   }
   return formattedEmail;
}

Co może być przydatne.

Zhaph - Ben Duguid
źródło
Czy możesz podać przykład klasy framwork zapewniającej tę metodę do zastąpienia? Jedyne powiązane rzeczy, które znam we frameworku, to IFormattibleinterfejs.
tm1
@ tm1 Każdy obiekt, który dziedziczy po, System.Objectbędzie miał ToString()metodę możliwą do zastąpienia , ale masz rację, że metoda programu formatującego nie overridepowinna i powinna odwoływać się do IFormattibleinterfejsu w celu zapewnienia pełnej zgodności.
Zhaph - Ben Duguid
Prawie - IFormattableprzyjmuje IFormatProviderparametr. Jednak dzięki edycji twojego posta.
tm1
Rzeczywiście, ma dwie metody, wartość, którą
wyrażałem,
3

Jedną z zalet zastąpienia ToString () jest obsługa narzędzi Resharper: Alt + Ins -> "Formatowanie elementów członkowskich" i zapisuje ToString () za Ciebie.

Daniel James Bryars
źródło
2

W niektórych przypadkach ułatwia to odczytywanie wartości klas niestandardowych w oknie nadzoru debugera. Jeśli dokładnie wiem, co chcę zobaczyć w oknie zegarka, kiedy nadpisuję ToString tymi informacjami, to widzę to.

filologon
źródło
1

Podczas definiowania struktur (efektywnie prymitywów użytkownika) uważam, że dobrą praktyką jest dopasowywanie metod ToStringi Parsei TryParse, szczególnie w przypadku serializacji XML. W takim przypadku skonwertujesz cały stan na ciąg, aby można go było odczytać później.

Klasy są jednak bardziej złożonymi strukturami, które zwykle są zbyt skomplikowane, aby można było używać ToStringi Parse. Ich ToStringmetody, zamiast zapisywać cały stan, mogą być prostym opisem, który pomaga zidentyfikować ich stan, na przykład unikalnym identyfikatorem, takim jak nazwa lub identyfikator, a może liczbą na liście.

Ponadto, jak powiedział Robbie, nadpisywanie ToStringumożliwia wywołanie ToStringodwołania tak podstawowego jak typ object.

Dave Cousineau
źródło
1

Możesz tego użyć, gdy masz obiekt, który nie ma intuicyjnego znaczenia reprezentacji ciągu, np. Osoba. Więc jeśli chcesz na przykład wydrukować tę osobę, możesz użyć tego zastąpienia do przygotowania jej formatu.

NickF
źródło
1

Object.ToStringMetoda powinna być używana tylko do celów debugowania. Domyślna implementacja pokazuje nazwę typu obiektu, która nie jest zbyt przydatna. Rozważ zastąpienie tej metody, aby zapewnić lepsze informacje do diagnostyki i debugowania. Proszę wziąć pod uwagę, że infrastruktury rejestrowania często używają metody ToString, więc te fragmenty tekstu znajdziesz w swoich plikach dziennika.

Nie zwracaj zlokalizowanych zasobów tekstowych w ramach Object.ToStringmetody. Powodem jest to, że metoda ToString powinna zawsze zwracać coś, co deweloper może zrozumieć. Deweloper może nie znać wszystkich języków obsługiwanych przez aplikację.

Wdrożyć ten IFormattableinterfejs, gdy chcesz powrócić zlokalizowaną tekst przyjazne dla użytkownika. Ten interfejs definiuje przeciążenie ToString z parametrami formati formatProvider. FormatProvider ułatwia formatowanie tekstu w sposób uwzględniający kulturę.

Zobacz także: Object.ToString i IFormattable

jbe
źródło
0

Prostsze zależy od tego, w jaki sposób Twoja nieruchomość będzie używana. Jeśli potrzebujesz sformatować łańcuch tylko raz, nie ma sensu go zastępować.

Jednak wydaje się, że zastępujesz metodę ToString, aby nie zwracać normalnych danych ciągu dla swojej właściwości, ale aby wykonać standardowy wzorzec formatowania. Ponieważ używasz string.format z dopełnieniem.

Ponieważ powiedziałeś, że się uczysz, ćwiczenie wydaje się również dotyczyć podstawowych zasad programowania obiektowego, związanych z hermetyzacją i ponownym wykorzystaniem kodu.

String.format przyjmujący argumenty, które ustawiłeś dla dopełnienia, zapewnia, że ​​właściwość zostanie sformatowana w ten sam sposób za każdym razem dla każdego kodu, który ją wywołuje. Idąc dalej, wystarczy zmienić to tylko w jednym miejscu zamiast w wielu.

Świetne pytanie, a także świetne odpowiedzi!

SoftwareCarpenter
źródło
0

Uważam, że przydatne jest zastąpienie metody ToString w klasach jednostek, ponieważ pomaga to szybko zidentyfikować problemy w testowaniu, zwłaszcza gdy asercja nie powiedzie się, konsola testowa wywoła metodę ToString na obiekcie.

Ale zgodnie z tym, co zostało powiedziane wcześniej, ma dać czytelną dla człowieka reprezentację danego obiektu.

ranjez
źródło
0

Jestem zadowolony z Wytycznych Ramowych, o których mowa w innych odpowiedziach. Chciałbym jednak podkreślić cel wyświetlania i debugowania.

Uważaj, jak używasz ToStringw swoim kodzie. Twój kod nie powinien opierać się na łańcuchowej reprezentacji obiektu. Jeśli tak, należy bezwzględnie zapewnić odpowiednie Parsemetody.

Ponieważ ToStringmoże być używany wszędzie, może być problemem związanym z konserwacją, jeśli chcesz zmienić reprezentację ciągu obiektu w późniejszym czasie. W tym przypadku nie można po prostu zbadać hierarchii wywołań, aby zbadać, czy jakiś kod się nie zepsuje.

tm1
źródło