Техника условной компиляции в C # для получения результатов без операций - PullRequest
2 голосов
/ 12 ноября 2010

Кто-нибудь знает хороший способ (с помощью отражения или специальных атрибутов) заменить определенные вызовы функций на no-ops в C #?

По сути, я пытаюсь сделать что-то вроде этого

#ifdef DEBUG

StopWatch.start();

#endif

DoSomething();

#ifdef DEBUG

StopWatch.stop();
Log.TimingInfo(StopWatch);

#endif

без разбрасывания множества ifdefs повсюду в моем коде. Я мог бы заменить это (мой класс StopWatch) шаблоном нулевого объекта и условно назначить ему нулевой объект, но это все еще не идеально по сравнению со строгим запретом в коде. Длина пути кода здесь очень важна, и я бы предпочел пожертвовать некоторой способностью к чтению из-за того, что у нас не было абсолютно никаких операций, когда мы не пытаемся собирать результаты синхронизации.

Кто-нибудь знает, есть ли способ пометить мой класс или методы StopWatch в C #, чтобы просто не выдавать код при оценке компилятором?

Ответы [ 3 ]

11 голосов
/ 12 ноября 2010

Вы можете аннотировать свои методы с помощью атрибута [Conditional("DEBUG")], например:

class StopWatch
{
    [Conditional("DEBUG")]
    public void Start() { }

    [Conditional("DEBUG")]
    public void Stop() { }
}

Это имеет тот же эффект, что и #ifdef DEBUG при вызовах на Start / Stop. Одно предостережение: условные методы должны возвращать void. Есть и несколько других ограничений. Подробнее см. Документацию ConditonalAttribute .

2 голосов
/ 12 ноября 2010

Если вы используете C # 3.0 или более позднюю версию, вы можете посмотреть на частичные методы:

http://bartdesmet.net/blogs/bart/archive/2007/07/28/c-3-0-partial-methods-what-why-and-how.aspx

0 голосов
/ 28 июня 2012

Вы можете использовать такой класс, он также включает запись в окно вывода visual studio:

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));
    }
}

и «как пользоваться»:

TimerCalls.StartStopwatch("Operations");
// many operations..
TimerCalls.StopStopwatch("Operations");// Timer: Operations, 508ms ---- 27.06.2012 11:41:06

Используется условный символ ТАЙМЕРЫ, который можно добавить в вашу программу через свойства проекта Visual Studio или с помощью #define (уверен, что вам придется иметь дело со штрафами за время создания класса). Вы можете прочитать больше об этом в моем блоге . Но это по-русски.

...