开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜