20 Mar
One of the great features of Visual Studio is its debugging interface. The ability to watch variables change through the code and inspect them on the fly is invaluable. The on-hover inspection and quickwatch dialogs are great if you’re dealing with lots of variables or long lists that need analysing. Being able to view the value of a whole list of objects at once is great. But this only works for simple data type objects (string, int, float, etc.). More complex objects just show the fully qualified type name. This can become really frustrating if you’ve got a long list of objects and you’re trying to find a specific one.
The reason for this difference is that when it’s displaying your variables, the watch dialog does an implicit ToString() call to display the ‘value’ column. If ToString() hasn’t been implemented, it calls the ToString() method of the base object type, which as mentioned, just returns the fully qualified type. However if you do implement ToString(), it can be a God-send when you’re debugging.
Here’s a trivial example:
Lets say I’ve got a class ‘Make’ which represents a car make (i.e. Holden, Ford, etc.)
1: public class Make
2: {
3: public Make(string name)
4: {
5: _name = name;
6: }
7:
8: private string _name;
9: public string Name
10: {
11: get { return _name; }
12: set { _name = value; }
13: }
14: }
Now this is obviously a fairly useless class, but it will do for the sake of example. In my program I’ve created a Generic List of Makes
1: List<Make> makes = new List<Make>();
and populated it with all the makes from drive.com.au. So this is a list of 151 makes. If I inspect this list while debugging I see this. Not really very helpful. To find an individual make, I’ve got to expand each one until I find it. Now this is a list of very simple objects, and they’re sorted alphabetically. But what if the property that I was looking for was actually a sub-property, so I would have to expand multiple times. This becomes real annoying really fast.
If you add a toString() property to your object that returns some unique information about the specific instance of your object (in this case, the ‘Name’ property) things become much easier.
So with this object:
1: public class Make
2: {
3: public Make(string name)
4: {
5: _name = name;
6: }
7:
8: private string _name;
9: public string Name
10: {
11: get { return _name; }
12: set { _name = value; }
13: }
14:
15: public new string ToString()
16: {
17: return Name;
18: }
19: }
We now get this Quickwatch dialog. As you can see, much easier to find something.
Now as I said, this was a trivial, nonsense example, but imagine a list of complex objects that have no one single identifying property. Keeping with the cars theme, think of a list of search results, say this list. There are a list of listing objects with numerous properties. Just displaying “Make”, or even the “Make, Model” wouldn’t help, it would need a combination of probably “Make, Model, Series, Year, Price, [Dealer|Private]“. That would provide a unique string to identify the objects (or at least unique enough). To do this it would simply be a matter of something like this:
1: public new string ToString()
2: {
3: return String.Format("{0}, {1}, {2}, ${3}, {4}", Make, Model, Series, Price, SellerType);
4: }
Now I know some people hate the idea of code sitting there that serves no purpose at production level, so if you’re really concerned about keeping the size of your assemblies down, just wrap the ToString() method in a #if DEBUG block.
This is such a simple little thing, but it can save heaps of time when debugging.