Код "Лише налагодження", який повинен працювати, лише коли "ввімкнено"


93

Я хотів би додати трохи коду 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. Щось ще?

Відповіді:


145

Змінна екземпляра, мабуть, буде способом робити те, що ви хочете. Ви можете зробити його статичним, щоб зберегти одне і те ж значення протягом життя програми (або потоку, залежно від вашої статичної моделі пам’яті), або зробити його звичайним екземпляром 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 має вбудовану відповідь на половину цієї проблеми, використовуючи атрибут "Умовний".

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, і у збірці випуску її значення не має значення, це досить нешкідливо.


2
Нарешті - той, хто прочитав все питання. Дякую, добре - це здавалося начебто тривалим рішенням (потрібно мати два розділи препроцесора), але, мабуть, це найкращий C # для того, що я хочу.
Matt Smith

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
Використовуючи атрибут, вам не потрібно писати суфікс "атрибут". Умовний = УмовнийАтрибут. Клас атрибутів повинен закінчуватися на "Атрибут", але його можна опустити, коли він використовується як атрибут у коді. Її легше читати, якщо суфікс пропущено.
Eric Ouellet

23

Ви можете спробувати це, якщо вам потрібен код для запуску лише тоді, коли до процесу приєднаний налагоджувач.

if (Debugger.IsAttached)
{
     // do some stuff here
}

Дякую! Це саме те, що я хотів: зробити Console.ReadLine () наприкінці, щоб запобігти закриттю вікна консолі під час налагодження.
VVS

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).


3

Якщо ви хочете знати, чи є налагодження, будь-де в програмі. Використовуй це.

Оголосити глобальну змінну.

bool isDebug=false;

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

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

У методі ініціалізації викличте функцію

isDebugging();

Тепер у всій програмі. Ви можете перевірити налагодження та виконати операції. Сподіваюся, це допомагає!


1
AFAIK: це та його варіанти - це лише надійний спосіб дізнатись, чи миття програми складено із встановленим прапором налагодження.
LosManos,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.