C# - Diretivas de pré-processamento


As diretivas de pré-processamento suprem o compilador com informações adicionais sobre regiões de código.

As diretivas de pré-processamento mais comuns são as diretivas condicionais, que fornecem uma maneira de incluir ou excluir regiões de código a partir da compilação.

Obs: Na linguagem C# não existe uma etapa separada de pré-processamento as diretivas são processadas durante o processo de compilação.

O trecho de código abaixo mostra a utilização das diretivas de pré-processamento em um programa console na linguagem C#:

# define DEBUG
using System;

namespace Diretivas_PreProcessamento
{
    class MacorattiClass
    {
        int x;
        void Nada()
        {
        # if DEBUG
        Console.WriteLine ("Testando: x = {0}", x);
        # endif
        }
        //...
    }
}
Nesta classe, a declaração na classe MacorattiClass é compilada como condicionalmente  dependente da presença do símbolo DEBUG.

Se o símbolo DEBUG for removido a declaração não é compilado.

Símbolos de pré-processamento pode ser definido dentro de um arquivo de origem (como temos fizemos ao lado), e eles podem ser passados para o compilador com a opção de  linha de comando /define: símbolo

A utilização das diretivas de pré-processamento deve seguir as seguintes regras:

  • Uma diretiva de pré-processamento em C# deve ser a única instrução em uma linha e deve começar com o símbolo “#” (espaços em branco são permitidos antes e depois do simbolo “#”.)
  • Um identificador deve ser usado logo após o simbolo “#”; O junção do símbo “#” + identificador  forma o nome da diretiva;
    Ex: “#endif” é o nome da diretiva de pré-processamento.

A seguir temos as diretivas de pré-processamento usadas na linguagem C#:

Em geral podemos utilizar as diretivas nas seguintes situações:

A base das diretivas de pré-processamento na linguagem C# são as diretivas #define e #undef. Elas permitem que você crie e destrua os símbolos utilizados pela etapa de pré-processamento. Você pode user este revurso para construir os scripts que produzem diferentes versões do seu código. Por exemplo, uma versão "completa" e uma versão "demo" limitada.

As diretivas #if, #elif, #else e #endif são usadas no pré-processamento condicional verificando se um símbolo é verdadeiro ou não.

Podemos usar as diretivas para excluir partes do código de ser visto pelo compilador. Dessa forma excluídos do assembly eles nunca serão vistos em tempo de execução. Isso é diferente de um bloco de código regular, if(x){} onde o código é realmente compilado, avaliado em tempo de execução e adicionado ao conjunto.

Dessa forma compilação condicional permite facilmente controlar em tempo de compilação qual código incluir em seu programa você pode assim ligar e desligar a inclusão de código de depuração. Quando você está de codificando e debugando isso lhe permite testar seu código, mas esse código não deve estar presente na versão de produção do seu software.

Exemplos de utilização das diretivas de pré-processamento

1 - Utilização das diretivas #define, #if, #else e #endif;

A diretiva #define definiu o símbolo TESTE e a diretiva #if verificando a sua existência executou o código pertinente:

Podemos excluir a diretiva #define e realizar a definição na linha de comando de compilação da seguinte forma: csc  /define:TESTE Programa.cs

As diretivas #if e #elif podem ser usadas com os operadores ||, &&, e ! para realizar as operações or, and e not com mais de um símbolo.

Ex: #if TESTE && !DEBUG

O exemplo a diretiva instrui o compilador a incluir o código que segue se o símbolo TESTE for definido e o símbolo DEBUG não for definido.

2 - Utilização das diretiva #error, #warning

a- #error

A diretiva #error cria um erro de compilação. Quando esta diretiva é atingida, o programa não vai compilar.

O exemplo acima mostra o erro na Error List da aplicação.

b- #warning

A diretiva #warning acrescenta um alerta em tempo de compilação.

O exemplo abaixo mostra os alertas na lista de alertas da aplicação:

3 - Utilização das diretiva #line

A diretiva #line especifica o número da linha original e nome do arquivo fonte para a entrada posterior no arquivo de entrada do pré-processador atual

Atributos Condicionais

Um atributo decorado com o atributo Conditional será compilada apenas se uma dado símbolo do pré-processador estiver presente.

O atributo condicional permite a definição de métodos condicionais. O atributo condicional indica uma condição pelo teste de um símbolo de compilação condicional.

As chamadas para um método condicional são incluídos ou omitidos, dependendo se esse símbolo é definido no ponto da chamada. Se o símbolo é definido, a chamada é incluída, caso contrário, a chamada (incluindo a avaliação dos parâmetros da chamada) é omitida.

Um método condicional está sujeita às seguintes restrições:

Exemplo:

No exemplo acima temos a declaração de Class1.M como um método condicional.

O método Teste de Class2 chama esse método. Desde que símbolo DEBUG de compilação condicional for definido, se Class2.Teste for referenciada , ela irá chamar o método M. Se o símbolo DEBUG não for definido, então Class2.Teste não chamará Class1.M.

É importante notar que a inclusão ou exclusão de uma chamada para um método condicional é controlado pelos símbolos de compilação condicional no ponto da chamada.

A diretiva #pragma Warning

Os avisos do compilador podem ser extremamente valiosos para detectar erros. Para isso, o compilador permite que você seletivamente suprima avisos com a diretiva #pragma warning.

A diretiva #pragma warning pode ser usada para habilitar ou desabilitar certos alertas. O compilador gera um aviso quando vê algo no seu código que parece intencional. Ao contrário dos erros, avisos normalmente não impedem que seu aplicativo de seja compilado.

Sintaxe:

#pragma warning disable warning-list
#pragma warning restore warning-list

Após a diretiva #pragma seguida da palavra warnig podemos declarar uma lista separada por vírgula com os números dos alertas que desejamos desativar ou restaurar.

Exemplo:

// pragma_warning.cs
using System;

#pragma warning disable 414, 3021
[CLSCompliant(false)]
public class C
{
    int i = 1;
    static void Main()
    {
    }
}
#pragma warning restore 3021
[CLSCompliant(false)]  // CS3021
public class D
{
    int i = 1;
    public static void F()
    {
    }
}

Quando os números dos alertas não forem especificados, a palavra disable desativa todos os alertas e a palavra restore restaura todos os avisos.

Neste exemplo, nós instruímos o compilador para não nos avisar sobre a Mensagem do campo que não está sendo usado:

public class Teste
{

static void Main() { }
    #pragma warning disable 414
    static string Mensagem = "Olá, Macoratti";
    #pragma warning restore 414
}

O compilador gera um aviso quando ele detectar algo no seu código que parece intencional. Ao contrário dos erros, os alertas normalmente não impedem que seu aplicativo de compilação.

Vamos ver um exemplo para ilustrar melhor a utilização deste recurso.

Se você tentar compilar o código abaixo:

using System;

namespace Diretivas_PreProcessamento
{
    class Program
    {
        static void Main(string[] args)
        {
            int naoUtilizado;
            int atribuido = 3;
        }
    }
}

Dois avisos são gerados para o código acima. Um indica que a variável naoUtilizado não é utilizada, e a segunda afirma que a variável atribuido tem um valor atribuído, mas nunca é usada novamente. Ambas as condições podem indicar um problema com o código fonte. Os avisos devem ser semelhantes aos mostrados a seguir:

Às vezes avisos gerados durante uma compilação são esperados. Você pode preferir esconder tais avisos para que outros problemas sejam mais fáceis de detectar. Isto pode ser conseguido usando a diretiva do compilador #pragma warning.

Para desativar avisos, uma lista separada por vírgulas de números de aviso é fornecida para a diretiva, juntamente com a palavra-chave disable. A lista deve conter apenas a parte inteira dos números de aviso. Todos os avisos dos tipos especificados são ignorados a partir da posição da diretiva até ao final do processo.

Para desativar as duas advertências mencionadas acima, que têm os códigos CS0169 e CS0414, use a diretiva com disable conforme mostrado abaixo. Tentar compilar o código novamente para ver que as advertências não são mais relatadas.

Você deve suprimir os avisos do compilador para o menor número de linhas de código possível para evitar o risco de que as advertências inesperadas sejam ocultadas. Para reativar os avisos, a palavra-chave restore é usada, como mostrado abaixo:

Rom 3:10 como está escrito: Não há justo, nem sequer um.

Rom 3:11 Não há quem entenda; não há quem busque a Deus.

Rom 3:12 Todos se extraviaram; juntamente se fizeram inúteis. Não há quem faça o bem, não há nem um só.

Referências:


José Carlos Macoratti