Why / when would it be appropriate to override ToString?
Overriding ToString()
allows you to give a useful human-readable string representation of a class.
This means that the output can reveal useful information about your class. For example, if you had a Person class you might choose to have the ToString()
output the person's id, their firstname, their lastname etc. This is extremely useful when debugging or logging.
With regard to your example - it is difficult to tell if your override is useful without knowing what this class is - but the implementation itself is ok.
I'm just going to give you the answer straight from the Framework Design Guidelines from the .NET Development Series.
AVOID throwing exceptions from ToString
CONSIDER returning a unique string associated with the instance.
CONSIDER having the output of ToString
be a valid input for any parsing methods on this type.
DO ensure that ToString
has no observable side effects.
DO report security-sensitive information through an override of ToString
only after demanding an appropriate permission. If the permission demand fails, return a string excluding security-sensitive information.
The Object.ToString
method is intended to be used for general display and debugging purposes. The default implementation simply provides the object type name. The default implementation is not very useful, and it is recommended that the method be overridden.
DO override ToString
whenever an interesting human-readable string can be returned. The default implementation is not very useful, and a custom implementation can almost always provide more value.
DO prefer a friendly name over a unique but not readable ID.
It is also worth mentioning as Chris Sells also explains in the guidelines that ToString
is often dangerous for user interfaces. Generally my rule of thumb is to expose a property that would be used for binding information to the UI, and leave the ToString
override for displaying diagnostic information to the developer. You can also decorate your type with DebuggerDisplayAttribute
as well.
DO try to keep the string returned from ToString
short. The debugger uses ToString
to get a textual representation of an object to be shown to the developer. If the string is longer than the debugger can display, the debugging experience is hindered.
DO string formatting based on the current thread culture when returning culture-dependent information.
DO provide overload ToString(string format)
, or implement IFormattable
, if the string return from ToString
is culture-sensitive or there are various ways to format the string. For example, DateTime
provides the overload and implements IFormattable
.
DO NOT return an empty string or null from ToString
I swear by these guidelines, and you should to. I can't tell you how my code has improved just by this one guideline for ToString
. The same thing goes for things like IEquatable(Of T)
and IComparable(Of T)
. These things make your code very functional, and you won't regret taking the extra time to implement any of it.
Personally, I've never really used ToString
much for user interfaces, I have always exposed a property or method of some-sort. The majority of the time you should use ToString
for debugging and developer purposes. Use it to display important diagnostic information.
It's always appropriate but carefully consider the intentions behind what you're displaying
A better question would be to ask:
Why would one override ToString()?
ToString() is the window into an object's state. Emphasis on state as a requirement. Strongly OOP languages like Java/C# abuse the OOP model by encapsulating everything in a class. Imagine you are coding in a language that doesn't follow the strong OOP model; consider whether you'd use a class or a function. If you would use it as a function (ie verb, action) and internal state is only maintained temporarily between input/output, ToString() won't add value.
Like others have mentioned, it's important to consider what you output with ToString() because it could be used by the debugger or other systems.
I like to imagine the ToString method as the --help parameter of an object. It should be short, readable, obvious, and easy to display. It should display what the object is not what it does. With all that in mind let's consider...
Use Case - Parsing a TCP packet:
Not an application-level-only network capture but something with more meat like a pcap capture.
You want to overload ToString() for just the TCP layer so you can print data to the console. What would it include? You could go crazy and parse all of the TCP details (ie TCP is complex)...
Which includes the:
- Source Port
- Destination Port
- Sequence Number
- Acknowledgment number
- Data offset
- Flags
- Window Offset
- Checksum
- Urgent Pointer
- Options (I'm not even going to go there)
But would you want to receive all that junk if you were calling TCP.ToString() on 100 packets? Of course not, it would be information overload. The easy and obvious choice is also the most sensible...
Expose what people would expect to see:
- Source Port
- Destination Port
I prefer a sensible output that's easy for humans to parse but YMMV.
TCP:[destination:000, source:000]
Nothing complex, the output isn't for machines to parse (ie unless people are abusing your code), the intended purpose is for human readability.
But what about all the rest of that juicy info I talked about before, isn't that useful too? I'll get to that but first...
ToString() one of the most valuable and underused methods of all time
For two reasons:
- People don't understand what ToString() is for
- The base 'Object' class is missing another, equally important, string method.
Reason 1 - Don't abuse the usefulness of ToString():
A lot of people use ToString() to pull a simple string representation of an object. The C# manual even states:
ToString is the major formatting method in the .NET Framework. It converts an object to its string representation so that it is suitable for display.
Display, not further processing. That doesn't mean, take my nice string representation of the TCP packet above and pull the source port using a regex ::cringe::.
The right way to do things is, call ToString() directly on the SourcePort property (which BTW is a ushort so ToString() should already be available).
If you need something more robust to package the state of a complex object for machine parsing you'll be better off using a structured serialization strategy.
Fortunately, such strategies are very common:
- ISerializable (C#)
- Pickle (Python)
- JSON (Javascript or any language that implements it)
- SOAP
- etc...
Note: Unless you're using PHP because, herp-derp, there's a function for that ::snicker::
Reason 2 - ToString() is not enough:
I have yet to see a language that implements this at the core but I have seen and used variations of this approach in the wild.
Some of which include:
- ToVerboseString()
- ToString(verbose=true)
Basically, that hairy mess of a TCP Packet's state should be described for human readability. To avoid 'beating a dead horse' talking about TCP I'll 'point a finger' at the #1 case where I think ToString() and ToVerboseString() are underutilized...
Use Case - Arrays:
If you primarily use one language, you're probably comfortable with that language's approach. For people like me who jump between different languages, the number of varied approaches can be irritating.
Ie, the number of times this has irritated me is greater than the sum of all of the fingers of every Hindu god combined.
There are various cases where languages use common hacks and a few that get it right. Some require wheel re-inventing, some do a shallow dump, others do a deep dump, none of them work the way I'd like them to...
What I'm asking for is a very simple approach:
print(array.ToString());
Outputs: 'Array[x]' or 'Array[x][y]'
Where x is the number of items in the first dimension and y is the number of items in the second dimension or some value that indicates that the 2nd dimension is jagged (min/max range maybe?).
And:
print(array.ToVerboseString());
Outputs the whole she-bang in pretty-print because I appreciate pretty things.
Hopefully, this sheds some light on a topic that has irked me for a long time. At the very least I sprinkled a little troll-bait for the PHPers to downvote this answer.
Do you need to override
ToString
? No.Can you get a string representation of your object in another way? Yes.
But by using ToString
you are using a method that is common to all objects and thus other classes know about this method. For instance, whenever the .NET framework wants to convert an object to a string representation, ToString
is a prime candidate (there are others, if you want to provide more elaborate formatting options).
Concretely,
Console.WriteLine(yourObject);
would invoke yourObject.ToString()
.