Код «Только отладка», который должен запускаться только при «включении»

94

Я хотел бы добавить код C # «только отладка», который запускается только в том случае, если его запрашивает отладчик. В C ++ я делал что-то похожее на следующее:

void foo()
{   
  // ...
  #ifdef DEBUG
  static bool s_bDoDebugOnlyCode = false;
  if (s_bDoDebugOnlyCode)
  {
      // Debug only code here gets executed when the person debugging 
      // manually sets the bool above to true.  It then stays for the rest
      // of the session until they set it to false.
  }
  #endif
 // ...
}

Я не могу сделать то же самое в C #, поскольку нет локальной статики.

Вопрос : Как лучше всего добиться этого на C #?

  1. Следует ли использовать статическое поле частного класса с директивами препроцессора C # ( #if/#endif DEBUG)?
  2. Должен ли я использовать атрибут Conditional (для хранения кода), а затем статическое поле частного класса ( не окруженное директивами препроцессора C # #if/#endif DEBUG?).
  3. Что-то другое?
Мэтт Смит
источник

Ответы:

147

Переменная экземпляра, вероятно, будет способом делать то, что вы хотите. Вы можете сделать его статическим, чтобы сохранять одно и то же значение в течение всего срока службы программы (или потока, в зависимости от вашей модели статической памяти), или сделать его обычным экземпляром var, чтобы контролировать его в течение срока службы экземпляра объекта. Если этот экземпляр синглтон, они будут вести себя точно так же.

#if DEBUG
private /*static*/ bool s_bDoDebugOnlyCode = false;
#endif

void foo()
{   
  // ...
#if DEBUG
  if (s_bDoDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }
#endif
 // ...
}

Чтобы быть полными, прагмы (директивы препроцессора) считаются своего рода кладжем для управления потоком программы. У .NET есть встроенный ответ на половину этой проблемы с использованием атрибута «Conditional».

private /*static*/ bool doDebugOnlyCode = false; 
[Conditional("DEBUG")]
void foo()
{   
  // ...    
  if (doDebugOnlyCode)
  {
      // Code here gets executed only when compiled with the DEBUG constant, 
      // and when the person debugging manually sets the bool above to true.  
      // It then stays for the rest of the session until they set it to false.
  }    
  // ...
}

Никаких прагм, намного чище. Обратной стороной является то, что Conditional может применяться только к методам, поэтому вам придется иметь дело с логической переменной, которая ничего не делает в сборке выпуска. Поскольку переменная существует исключительно для переключения с хоста выполнения VS, а в сборке релиза ее значение не имеет значения, оно довольно безвредно.

KeithS
источник
2
Наконец - тот, кто прочитал весь вопрос. Спасибо, хорошо - это казалось долгим решением (необходимость иметь две секции препроцессора), но, возможно, это лучшее, что C # может сделать для того, что я хочу.
Мэтт Смит
6
Мех. Я бы не назвал это длинным только потому, что вы добавили еще две строки директивы препроцессора.
KeithS
4
Что ж, большое спасибо, Патрик, за то, что проголосовал против принятого ответа 3-летней давности в пользу того, который не решает всей проблемы. Условный атрибут только предотвращает выполнение метода в режимах без отладки. OP хотел не только этого, но и иметь возможность «включить» код с помощью отладчика. И используемый тег gokkor не компилируется.
KeithS
2
Обратите внимание, что препроцессор сообщает вам, компилируется ли программа в режиме отладки, но не сообщает, действительно ли отладчик работает.
Шейн
65

Вы ищете

[ConditionalAttribute("DEBUG")]

атрибут.

Если вы, например, напишите такой метод, как:

[ConditionalAttribute("DEBUG")]
public static void MyLovelyDebugInfoMethod(string message)
{
    Console.WriteLine("This message was brought to you by your debugger : ");
    Console.WriteLine(message);
}

любой вызов этого метода внутри вашего собственного кода будет выполняться только в режиме отладки. Если вы собираете свой проект в режиме выпуска, даже вызов «MyLovelyDebugInfoMethod» будет проигнорирован и выгружен из вашего двоичного файла.

Да, и еще одна вещь, если вы пытаетесь определить, отлаживается ли ваш код в данный момент в момент выполнения, также можно проверить, перехватывается ли текущий процесс JIT. Но это все вместе другой случай. Оставьте комментарий, если это то, что вы пытаетесь сделать.

Гоккор
источник
3
При использовании атрибута вам не нужно писать суффикс «атрибут». Условный = Условный атрибут. Класс атрибута должен заканчиваться на «Атрибут», но его можно опустить при использовании в качестве атрибута в коде. Легче читать, если опустить суффикс.
Эрик Уэлле
23

Вы можете попробовать это, если вам нужен только код для запуска, когда к процессу подключен отладчик.

if (Debugger.IsAttached)
{
     // do some stuff here
}
Уэс
источник
Спасибо! Это именно то, что я хотел: сделать Console.ReadLine () в конце, чтобы предотвратить закрытие окна консоли при отладке.
ВВС
4

Думаю, стоит упомянуть, что это [ConditionalAttribute]находится в System.Diagnostics;пространстве имен. Я немного споткнулся, когда получил:

Error 2 The type or namespace name 'ConditionalAttribute' could not be found (are you missing a using directive or an assembly reference?)

после использования в первый раз (думал, будет в System).

XyberICE
источник
3

Если вы хотите знать, есть ли отладка, везде в программе. Использовать это.

Объявить глобальную переменную.

bool isDebug=false;

Создать функцию для проверки режима отладки

[ConditionalAttribute("DEBUG")]
    public static void isDebugging()
    {
        isDebug = true;
    }

В методе инициализации вызовите функцию

isDebugging();

Теперь по всей программе. Вы можете проверить наличие отладки и выполнить операции. Надеюсь это поможет!

Мохамед Алихан
источник
1
AFAIK: этот и его варианты - единственный верный способ узнать, скомпилирована ли программная стирка с установленным флагом отладки.
LosManos