Using in-line delegates for logging

Any work you have to do to collate infomation destined for a log is wasted effort if that logging is switched off or otherwise configured such that your log message will never be output.

This inevitably leads to code along the following lines:


if (loggingEnabled)
{
   int messageLength = message.GetLength();
   Logger.Write(String.Format("The message is {0} bytes long.", messageLength));
}

Of course – we can factor out the if statement into a helper method like so:


public static class LoggingHelper
{
   public static void Log(string logMessage)
      {
         if (loggingEnabled)
            Logger.Write(logMessage);
      }
}

…and then call it from our code like this:


int messageLength = message.GetLength();
LoggingHelper.Log(String.Format("The message is {0} bytes long.", messageLength));

– but that isn’t really the point. The most expensive operation in the above code sample might be the call to message.GetLength(). In that case we still have to perform the most expensive operation in our logging code before passing our constructed log message to our logging helper method.

I’ve found that this is a really good application for in-line delegates. If you’ve never used in-line delegates before – they are a neat feature availble from C#2.0 which allow you to specify the body of a delegate in-line. For more on in-line delegates, check here.

Our LoggingHelper code can be re-arranged thus:


public static class LoggingHelper
{
	public static void Log(GetLogMessage getLogMessage)
	{
		if (loggingEnabled)
			Logger.Write(getLogMessage());
	}

	public delegate string GetLogMessage();

}

…and called like this:


LoggingHelper.Log(
            delegate()
            {
               return String.Format("The message is {0} bytes long.", message.GetLength());
            });

In this case the call to message.GetLength() only happens when logging is enabled.

In-line delegates make this approach very compelling as everything that is in scope in the calling method is available to the delegate… not so if the delegate is defined elsewhere. Ideal for logging.

About Adam

Comments

3 Responses to “Using in-line delegates for logging”
  1. silky says:

    so delegate creation is cheaper?

  2. Adam says:

    The cost of creating the delegate is at compile time. Think of the delegate as a function pointer. If the delegate is not called then there is no run-time cost associated with it. I’m not sure exactly what the MSIL looks like, but I have profiled this approach and it’s as good as putting an if block around each log line. The synatx gets a little neater when using a lambda expression in C# 3.0 instead of the delegate syntax – but this is just further syntax sugar, and not always possible if many lines of code are required.

  3. silky says:

    well in that case; nice :)

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!