И объединять или отменять символы ConditionaAttribute, чтобы избежать генерации вызова MSIL - PullRequest
0 голосов
/ 01 июня 2019

Мне нужно сделать некоторую условную компиляцию в C #, но мне также было предложено сохранить глобальное количество символов низким.Так что вместо #if ENABLE_MODULE (и добавления большого количества символов) я в основном отключаюсь #if !DISABLE_MODULE.

При профилировании циклов ядра я хочу иметь точный контроль над тем, что отключается, чтобы иметьчище посмотрим на результаты.Но даже для пустых вызовов assert (#if внутри тела метода) одни вызовы суммируют значительное время.Вот почему я начал использовать атрибут [Conditional], чтобы полностью удалить вызов и избежать необходимости заключать все в разделы #if, которые делают код менее читабельным.

Но [Conditional] имеет некоторые предостережения:

  1. Можно редактировать только ИЛИ вместе.
  2. Отрицание с помощью not!внутреннее условное не допускается.
  3. Невозможно объединить их в AND.
  4. В отличие от #if, оно интерпретируется определениями символов области файла вызывающего абонента вместо фактическогоопределения символов в области имен файла метода.

Я нашел обходной путь, но он не изящный и имеет тенденцию повторять код (см. __Convoluted() методы ниже).Код внутри отключенных #if разделов обрабатывается как комментарии в Visual Studio (так что без рефакторинга имен), что делает его хуже, превращается в неработающие коммиты из-за не проверки всех комбинаций символов и т. Д.

Я думал об использовании некоторого зонтикасимволы, но это заставляет меня думать обо всем положительно-ИЛИ, и иногда я хочу, например, большинство утверждений, но не утверждать из какого-то модуля.

Может быть, это ответ на программную архитектуру, а не практическийone.

Я использую Unity, и поэтому не могу точно контролировать символы для каждой конфигурации (отладка / выпуск / сборка разработки), не выполняя некоторые сценарии сборки, которые заменяют параметры компилятора внутри файла (csc.rsp)

Мой вопрос: есть ли лучший способ справиться с этим?

Спасибо за ваше время.

Я сделал немного домашней работыпробовал разные альтернативы и пришел к некоторым выводам (следующий код)

Минимальный тестовый пример C #. Консольное приложение .NET

Utility file

//ENABLE is a global symbol definition at project level

#if ENABLE && EXTRA
    #define _COMBINED
#endif

#if !ENABLE
    #define _DISABLE
#endif

using System;
using System.Diagnostics;

public static class Utility {

    [Conditional("ENABLE")]
    public static void Call(string msg) {
        Console.WriteLine(msg);
    }

    [Conditional("ENABLE"), Conditional("OTHER")]
    public static void CallOr(string msg) {
        Console.WriteLine(msg);
    }

    [Conditional("_DISABLE")]
    public static void CallNot(string msg) {
        Console.WriteLine(msg);
    }

    public static void CallNotInternal(string msg) {
        CallNot(msg);
    }

    [Conditional("_COMBINED")]
    public static void CallAnd(string msg) {
        Console.WriteLine(msg);
    }

    public static void CallAndInternal(string msg) {
        CallAnd(msg);
    }

#if ENABLE //!_DISABLE
    [Conditional("_NEVER")] // <-- Hack to remove MSIL call.
    public static void CallNotConvoluted(string msg) { }
#else
    public static void CallNotConvoluted(string msg) {
        Console.WriteLine(msg);
    }   
#endif


#if !(ENABLE && EXTRA) //!_COMBINED
    [Conditional("_NEVER")] // <-- Hack to remove MSIL call.
    public static void CallAndConvoluted(string msg) { }
#else
    public static void CallAndConvoluted(string msg) {
        Console.WriteLine(msg);
    }   
#endif


}

Различные комбинации вызовов

//Works as expected
Utility.Call("Call1");

//Works as expected
Utility.CallOr("CallOr");

//Doesn't work because _DISABLE is not defined in this file
//(although it is defined at Utility)
Utility.CallNot("CallNot");

//Works because _DISABLE is defined at Utility (where CallNotInternal resides)
//BUT would have extra "empty" call
Utility.CallNotInternal("CallNotInternal");

//Doesn't work because _COMBINED is not defined in this file
//(although it is defined at Utility)
Utility.CallAnd("CallAnd");

//Works because _COMBINED is defined at Utility (where CallAndInternal resides)
//BUT would have extra "empty" call
Utility.CallAndInternal("CallAndInternal");

//Works but it seems kind of hacky/bulky
Utility.CallNotConvoluted("CallNotConvoluted");

//Works but it seems kind of hacky/bulky
Utility.CallAndConvoluted("CallAndConvoluted");

Код выводится, когда глобальные символы устанавливают следующее.Обратите внимание, что CallAnd и CallNot показывают, что Условное не работает как #if.

ENABLE and EXTRA
----------------
Call1
CallOr
CallAndInternal
CallAndConvoluted



ENABLE
-----
Call1
CallOr



(no symbols)
------------
CallNotInternal
CallNotConvoluted
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...