Pretty late answer but I leave for future reference. In my opinion you should consider Aspect Oriented Programming for tasks like this. That said if you don't need to add such complexity for a small task you may move preprocessor conditions to your log method:
public static void Log(string message)
{
#if DEBUG
// Do logging
#endif
}
Do not worry to leave an empty method, JIT will optimize it away and it won't even be called. It's almost equivalent to:
[Condition("DEBUG")]
public static void Log(string message)
Warning: I say almost because with a method with [Condition]
attribute arguments won't even be evaluated then given this code in release:
Log(String.Format("Index: {0}", index++));
index
variable won't ever be incremented, because JIT compiler won't emit call to Log
and even its arguments won't be evaluated. This is not true if you keep your method body empty with #if
directive inside it. Call won't be emitted (because of empty body) but its arguments will be evaluated.
Problem of this solution is that it'll clutter your normal program flow. With log calls, parameters dumping and stuff like that. What can you do?
Refactor your log
If you call SomeCode1() method many times you shouldn't log at each call site, much better is to move logging inside called method. Log only at beginning and end of each function, log will still be in your code but it'll be spanned across multiple functions.
void SomeCode1() {
Log("Starting SomeCode1");
// Do something
Log("SomeCode1 completed");
}
Your calling site will then be clean:
SomeCode1();
SomeCode2();
SomeCode3();
Expressions
If performance aren't an issue (measure, don't guess) you may use Expressions to do the trick for you. You can log parameters too (or fields, object status, diagnostic informations, invariants and whatever else you may need), everything controlled by diagnostic switches (to enable them only when required). No logging code in your LOB classes but price to pay is execution speed (and LoggedOperation
function complexity).
This code is (to be polite with myself) very naive, a decent implementation will be much more complex so just think about it as an idea more than an implementation.
static void LoggedOperation(Expression<Action> expression)
{
MethodCallExpression methodCall = expression.Body as MethodCallExpression;
if (methodCall != null)
Log("Calling {0}", methodCall.Method.Name);
expression.Compile()();
if (methodCall != null)
Log("{0} completed", methodCall.Method.Name);
}
It'll be then used like this:
LoggedOperation(() => SomeCode1());
LoggedOperation(() => SomeCode2());
LoggedOperation(() => SomeCode3());
You'll get:
Calling SomeCode1
SomeCode1 completed
Calling SomeCode2
SomeCode2 completed
Calling SomeCode3
SomeCode3 completed
AOP will give you a much cleaner code but this may be enough in many situations.