Código “somente depuração” que deve ser executado apenas quando “ativado”


92

Eu gostaria de adicionar algum código C # "somente depuração" que só é executado se a pessoa que está depurando o solicitar. Em C ++, eu costumava fazer algo semelhante ao seguinte:

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
 // ...
}

Não posso fazer exatamente o mesmo em C #, pois não há estática local.

Questão : Qual é a melhor maneira de fazer isso em C #?

  1. Devo usar um campo estático de classe privada com diretivas de pré-processador C # ( #if/#endif DEBUG)?
  2. Devo usar o atributo Conditional (para manter o código) e, em seguida, um campo estático de classe privada ( não cercado por diretivas de pré-processador C # #if/#endif DEBUG?).
  3. Algo mais?

Respostas:


145

Uma variável de instância provavelmente seria a maneira de fazer o que você deseja. Você pode torná-lo estático para persistir o mesmo valor durante a vida do programa (ou thread, dependendo do seu modelo de memória estática), ou torná-lo uma instância var comum para controlá-lo durante a vida de uma instância de objeto. Se essa instância for um singleton, eles se comportarão da mesma maneira.

#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
 // ...
}

Para completar, os pragmas (diretivas do pré-processador) são considerados um pouco complicados para usar para controlar o fluxo do programa. O .NET tem uma resposta incorporada para metade desse problema, usando o atributo "Condicional".

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.
  }    
  // ...
}

Sem pragmas, muito mais limpo. A desvantagem é que Condicional só pode ser aplicado a métodos, então você terá que lidar com uma variável booleana que não faz nada em uma versão de lançamento. Como a variável existe apenas para ser alternada do host de execução do VS, e em uma versão de compilação seu valor não importa, é bastante inofensivo.


2
Finalmente - alguém que leu a pergunta inteira . Obrigado, ok - parecia uma solução meio demorada (ter que ter as duas seções de pré-processador), mas talvez seja o melhor C # pode fazer para o que eu quero.
Matt Smith

6
meh. Eu não chamaria isso de extenso só porque você adiciona mais duas linhas de diretiva do pré-processador.
KeithS de

4
Bem, muito obrigado, Patrick, por votar contra uma resposta aceita de 3 anos de idade em favor de uma que não resolve todo o problema. O atributo condicional apenas evita que o método seja executado em modos de não depuração. O OP não queria apenas isso, mas ser capaz de "ativar" o código usando o depurador. E a tag do gokkor usada não compila.
KeithS de

2
Observe que o pré-processador informa se o programa está compilando no modo de depuração, mas não se o depurador está realmente em execução.
Shane

65

O que você está procurando é

[ConditionalAttribute("DEBUG")]

atributo.

Se você, por exemplo, escreve um método como:

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

qualquer chamada que você fizer a este método dentro de seu próprio código será executada apenas no modo de depuração. Se você construir seu projeto em modo de lançamento, até mesmo a chamada de "MyLovelyDebugInfoMethod" será ignorada e descartada de seu binário.

Ah, e mais uma coisa, se você está tentando determinar se o seu código está ou não sendo depurado no momento da execução, também é possível verificar se o processo atual está conectado por um JIT. Mas tudo isso junto é outro caso. Poste um comentário se é isso que você está tentando fazer.


3
Ao usar o atributo, você não precisa escrever o sufixo "Atributo". Conditional = ConditionalAttribute. Uma classe de atributo deve terminar com "Atributo", mas pode ser omitida quando usada como um atributo no código. É mais fácil ler quando o sufixo é omitido.
Eric Ouellet

23

Você pode tentar isso se só precisar que o código seja executado quando tiver um depurador anexado ao processo.

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

Obrigado! Isso é exatamente o que eu queria: Faça um Console.ReadLine () no final para evitar o fechamento da janela do console durante a depuração.
VVS

4

Acho que vale a pena mencionar que [ConditionalAttribute]está no System.Diagnostics;namespace. Eu tropecei um pouco quando cheguei:

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

depois de usá-lo pela primeira vez (pensei que teria sido System).


3

Se você quiser saber se está depurando, em todos os lugares do programa. Usa isto.

Declare a variável global.

bool isDebug=false;

Criar função para verificar o modo de depuração

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

No método de inicialização, chame a função

isDebugging();

Agora em todo o programa. Você pode verificar a depuração e fazer as operações. Espero que isto ajude!


1
AFAIK: isso e suas variantes são apenas uma maneira segura de saber se um programa foi compilado com o sinalizador de depuração definido.
LosManos
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.