Why / when would it be appropriate to override ToString?
C#OverridingC# Problem Overview
I'm studying C# and I wonder what the point and benefit of overriding ToString
might be, as shown in the example below.
Could this be done in some simpler way, using a common method without the override?
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;
}
C# Solutions
Solution 1 - C#
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.
Solution 2 - C#
-
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()
.
Solution 3 - C#
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.
Solution 4 - C#
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.
Solution 5 - C#
It's about good practise as much as anything, really.
ToString()
is used in many places to return a string representation of an object, generally for consumption by a human. Often that same string can be used to rehydrate the object (think of int
or DateTime
for example), but that's not always a given (a tree for example, might have a useful string representation which simply displays a Count, but clearly you can't use that to rebuild it).
In particular the debugger will use this to display the variable in the watch windows, immediate windows etc, therefore ToString
is actually invaluable for debugging.
In general, also, such a type will often have an explicit member that returns a string as well. For example a Lat/Long pair might have ToDecimalDegrees
which returns "-10, 50"
for example, but it might also have ToDegreesMinutesSeconds
, since that is another format for a Lat/Long pair. That same type might then also override ToString
with one of those to provide a 'default' for things like debugging, or even potentially for things like rendering web pages (for example, the @
construct in Razor writes the ToString()
result of a non-string expression to the output stream).
Solution 6 - C#
object.ToString()
converts an object to its string representation. If you want to change what is returned when a user calls ToString()
on a class you have created then you would need to override ToString()
in that class.
Solution 7 - C#
While I think the most useful information has already been provided, I shall add my two cents:
-
ToString()
is meant to be overridden. Its default implementation returns the type name which, while maybe useful at times (particularly when working with a lot of objects), doesn't suffice in the big majority of times. -
Remember that, for debugging purposes, you can rely on
DebuggerDisplayAttribute
. You can read more about it here. -
As a rule, on POCOs you can always override
ToString()
. POCOs are a structured representation of data, which usually can become a string. -
Design ToString to be a textual representation of your object. Maybe its main fields and data, maybe a description of how many items are in the collection, etc.
-
Always try to fit that string into a single line and have only essential information. If you have a
Person
class with Name, Address, Number etc. properties, return only the main data (Name some ID number). -
Be careful not to override a good implementation of
ToString()
. Some framework classes already implementToString()
. Overriding that default implementation is a bad thing: people will expect a certain result fromToString()
and get another.
Don't be really afraid of using ToString()
. The only thing I'd be careful about is returning sensitive information. Other than that, the risk is minimal. Sure, as some have pointed out, other classes will use your ToString whenever reaching for information. But heck, when does returning the type name will be considered better than getting some actual information?
Solution 8 - C#
If you don't override ToString
then you get your base classes implementation which, for Object
is just the short type name of the class.
If you want some other, more meaningful or useful implementation of ToString
then override it.
This can be useful when using a list of your type as the datasource for a ListBox
as the ToString
will be automatically displayed.
Another situtation occurs when you want to pass your type to String.Format
which invokes ToString
to get a representation of your type.
Solution 9 - C#
Something no one else has mentioned yet: By overriding ToString()
, you can also consider implementing IFormattable
so you can do the following:
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;
}
Which can be useful.
Solution 10 - C#
One benefit of overriding ToString() is Resharper's tooling support: Alt + Ins -> "Formatting members" and it writes the ToString() for you.
Solution 11 - C#
In some cases it makes it easier to read values of custom classes in the debugger watch window. If I know exactly what I want to see in the watch window, when I override ToString with that information, then I see it.
Solution 12 - C#
When defining structs (effectively user-primitives) I find it's good practice to have matching ToString
, and Parse
and TryParse
methods, particularly for XML serialization. In this case you will be converting the entire state to a string, so that it can be read from later.
Classes however are more compound structures that will usually be too complex for using ToString
and Parse
. Their ToString
methods, instead of saving the entire state, can be a simple description that helps you identify their state, like a unique identifier like a name or ID, or maybe a quantity for a list.
Also, as Robbie said, overriding ToString
allows you to call ToString
on a reference as basic as type object
.
Solution 13 - C#
You can use that when you have an object with not intuitive meaning of string representation, like person. So if you need for example to print this person you can use this override for preparing it's format.
Solution 14 - C#
The Object.ToString
method should be used for debugging purposes only. The default implementation shows the object type name which is not very useful. Consider to override this method to provide better information for diagnostics and debugging. Please consider that logging infrastructures often use the ToString method as well and so you will find these text fragments in your log files.
Do not return localized text resources within the Object.ToString
method. The reason is that the ToString method should always return something that the developer can understand. The developer might not speak all languages which the application supports.
Implement the IFormattable
interface when you want to return a user-friendly localized text. This interface defines a ToString overload with the parameters format
and formatProvider
. The formatProvider helps you to format the text in a culture aware way.
See also: Object.ToString and IFormattable
Solution 15 - C#
Simpler depends on how your property is going to be used. If you just need to format the string one time then it does not make that much sense overriding it.
However, It appears that you are overriding the ToString method to not return the normal string data for your property , but to perform a standard formatting pattern. Since you are using string.format with padding.
Because you said you are learning, the exercise appears to also hit on core principles in object oriented programming relating to encapsulation and code re-use.
The string.format taking the arguments you have set for padding ensures that the property will be formatted the same way each time for any code that calls it. As well, going forward you only have to change it in one place instead of many.
Great question and also some great answers!
Solution 16 - C#
I find it useful to override the ToString method on entity classes as it helps quickly identify issues in testing especially when an assertion fails the test console will invoke the ToString method on the object.
But in agreement with what has been said before it's to give a human readable representation of the object in question.
Solution 17 - C#
I'm happy with the Framework Guidelines referred to in other answers. However, I'd like to emphasize the display and debugging purposes.
Be careful about how you use ToString
in your code. Your code shouldn't rely on the string representation of an object. If it does, you should absolutely provide the respective Parse
methods.
Since ToString
can be used everywhere, it can be a maintainability pain point if you want to change the string representation of an object at a later point in time. You cannot just examine the call hierarchy in this case to study whether some code will break.