Conditional Compilation
The presence or absence of the DEBUG
and TRACE
symbols
tell the compiler how to handle calls to methods in the Debug
and Trace
classes.
If the DEBUG
or TRACE
symbols are not
defined, many of the method calls into the Debug
and Trace
classes
are optimized away completely. This can be a desirable feature for your own
types, and there are a number of ways to accomplish this with the .NET Framework
and the C# language.
One option is to bracket the calls with #if
/#endif
preprocessor
directives, as follows:
void DoWork() { #if METHODCALL Debug.WriteLine("MethodCall", "Entering MyClass::DoWork"); #endif Console.WriteLine("Working..."); }
Compiling this function with /d:METHODCALL
, DEBUG
results in a call to Debug.WriteLine
and a log of the method
entry. The downside to this approach is using preprocessor directives
such as this is arduous, error-prone, and the code quickly becomes unreadable.
An alternative is to use the ConditionalAttribute
custom
attribute. When placed on a method, this attribute instructs the C# compiler
to conditionally omit calls to the method.
Using this approach we can define a reflection-driven logger, as follows:
public class Logger { [Conditional("METHODCALL")] public static void LogMethodCall() { StackFrame sf = new StackFrame(1); // Get preceding stack frame MethodBase mb = sf.GetMethod(); // Get refl. info for method Type t = mb.DeclaringType; // Get refl. info for type string s = String.Format("Entering {0}::{1}", t.Name, mb.Name); Debug.WriteLine("MethodCall", ...
Get C# in a Nutshell now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.