Conditional compilation techniques in C# to get no-op results
Does anyone know a good way (either through reflection or special attributes) to replace certain functions calls with no-ops in C#?
Basically, what I'm trying to do is something like this
#ifdef DEBUG
StopWatch.start();
#endif
DoSomething();
#ifdef DEBUG
StopWatch.stop();
Log.TimingInfo(StopWatch);
#endif
without sprinkling a lot of ifdefs everywhere in my code. I could replace this (my StopWatch class) with a null object pattern and assign it the null object conditionally, but this is still not ideal compared to strictly no-op in the code. The code path length is very important here, and i'd rather sacrifice some read-ability for having absolutely no op when we're not trying to collect timing results.
Doe开发者_开发问答s anyone know if there is a way to tag my StopWatch class or methods in C# to simply not emit code when evaluated by the compiler?
You can annotate your methods with the [Conditional("DEBUG")]
attribute like:
class StopWatch
{
[Conditional("DEBUG")]
public void Start() { }
[Conditional("DEBUG")]
public void Stop() { }
}
This has the same effect as #ifdef DEBUG
around calls to Start
/Stop
. One caveat: conditional methods must return void. There are a few other restrictions as well. See the ConditonalAttribute documentation for details.
If you're on C# 3.0 or later, you could look into partial methods:
http://bartdesmet.net/blogs/bart/archive/2007/07/28/c-3-0-partial-methods-what-why-and-how.aspx
You can use such class, it also includes logging to visual studio's output window:
public static class TimerCalls
{
private static Dictionary _Stopwatches = new Dictionary();
[ConditionalAttribute("TIMERS")]
public static void StartStopwatch(string key)
{
if (_Stopwatches.ContainsKey(key)) //Stopwatch already running
return;
_Stopwatches.Add(key, Stopwatch.StartNew());
}
[ConditionalAttribute("TIMERS")]
public static void StopStopwatch(string key)
{
if (!_Stopwatches.ContainsKey(key))//No such stopwatch currently
return;
var watch = _Stopwatches[key];
watch.Stop();
_Stopwatches.Remove(key);
Debug.WriteLine(String.Format("Timer: {0}, {1}ms ---- {2}", key,
watch.Elapsed.TotalMilliseconds, DateTime.Now));
}
}
And "how to use":
TimerCalls.StartStopwatch("Operations");
// many operations..
TimerCalls.StopStopwatch("Operations");// Timer: Operations, 508ms ---- 27.06.2012 11:41:06
It uses conditional symbol TIMERS that can be added to your program via visual studio project properties or with #define(sure you will need to deal with the class creation time penalties). You can read more in my blog post about that. But its in russian.
精彩评论