In production environment, it is not always possible to step through the compiled code using a debugger and thus we rely on error logs to provide insights into the potential causes of bugs. The location of the bug, which is provided by the stacktrace of the exception, is not always helpful in determining the reason of the exception as the exception might be caused by data. So it is desirable to log not only the location of the error but also the object and the related object’s states (e.g. the value of the variables, etc).

One of the best places to insert logging code that captures object’s state would be in an object’s ToString method. By overriding the ToString method, an object can be visualized not only in debugging mode, but in shipped code as well. Another benefit of this approach is that the visualization can be many levels deep. For instance, if the objects that the current object has access to implement similar ToString methods, the states of all variables would be captured.

To illustrate this, let’s take a look at some code:

using System;

using System.Collections.Generic;

using System.Text;

namespace ExceptionHandling {

public class Record {

public string ObjName = string.Empty;

public string ObjColor = string.Empty;

public Record(string name, string color) { ObjName = name; ObjColor = color; } public override string ToString() { return string.Concat("{", ObjName, " — ", ObjColor, "}"); } }

public class Records {

public List<Record> records = null;

public Records() { records = new List<Record>(); }

public override string ToString() {

StringBuilder sb = new StringBuilder();

foreach (Record r in records) {

sb.Append(r.ToString());

sb.Append(Environment.NewLine);

} return sb.ToString();

}

}

}

As you can see in the code above, both Record and Records classes override the base ToString function and each outputs its member variables’ states.

To test our implemtation, consider the code below:

 

public void Test() {

Records r = new Records();

try {

r.records.Add(new Record("car", "red"));

r.records.Add(new Record("apple", "green"));

r.records.Add(new Record("sky", "blue"));

throw new Exception("This is a test");

}

catch (Exception e) {

Console.WriteLine(e.StackTrace);

Console.WriteLine(r.ToString());

}

}

Her we purposefully threw an exception and the second line writes out the object (note, here is the place where logging function would be placed).

The output of r.ToString() is:

{car — red}

{apple — green}

{sky — blue}

Be Sociable, Share!