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.