Diretivas de pré-processamento em C#

por Marcio Elias

No C#, não existe uma etapa separada de pré-processamento, as diretivas são processadas como parte da fase de análise léxica durante o processo de compilação. Assim para os programadores C, o termo “diretiva de pré-processamento” é usado apenas por uma questão de consistência.

Outro fato importante para os programadores C/C++ é que as diretivas em C# não podem ser usadas para criar macros.

Nesta página

Diretivas em C#
Explicando as diretivas
Conclusão:

Diretivas em C#

Uma diretiva de pré-processamento em C# deve ser a única instrução em uma linha e devem começar com “#”, embora espaços em branco sejam permitidos antes e depois do “#”.

Um identificador deve aparecer logo após o “#”, e este conjunto (“#” + identificador) é conhecido com o nome da diretiva, por exemplo, “#region” é o nome da diretiva.

Uma diretiva de pré-processamento pode ser usada nas seguintes situações:

  • 1. Compilação condicional. Nesta situação você pode, por exemplo, incluir ou excluir parte de um programa de acordo com situações diversas. Muito usado quando em conjunto com as diretivas #define/#undef.

  • 2. Controle de Linha. Se você usa um programa para combinar ou rearranjar arquivos fonte dentro de um arquivo intermediário, que será então compilado, você pode usar controle de linha para informar o compilador de onde cada linha veio originariamente.

  • 3. Relatório de Erro (Error) e avisos (Warning): A diretiva “#error” faz com que o pré-processamento reporte um erro fatal, já a diretiva “#warning” faz como que seja gerado um “aviso”, porém o pré-processado não é encerrado.

Abaixo segue uma lista de diretivas de pré-processamento suportadas pelo C#.

  • #if

  • #else

  • #elif

  • #endif

  • #define

  • #undef

  • #warning

  • #error

  • #line

  • #region

  • #endregion

Explicando as diretivas

As diretivas #if, #elif, #else e #endif são usadas no pré-processamento condicional, por exemplo, para verificar se um símbolo ou símbolos são verdadeiros. Se for verdadeiro o compilador verificará todo código localizando entre o “#if” e a próxima diretiva (que pode ser “#else”, “#elif” ou “#endif”). Sendo que a diretiva “#endif” é obrigatória quando do uso da diretiva “#if”.

Por exemplo, se no meio da programação precisar inserir um código específico ao momento de debug e outro para uma configuração específica podemos usar o seguinte código (No Visual Studio .NET escolha Console Application em C#):

#define DEBUG
#define OUTRA_SITUACAO
using System;

public class ClasseExemplo 
{
   public static void Main() 
   {
      #if (DEBUG && ! OUTRA_SITUACAO)
         Console.WriteLine("Código definido para DEBUG");
      #elif (!DEBUG && OUTRA_SITUACAO)
         Console.WriteLine("Código definido para OUTRA_SITUACAO ");
      #elif (DEBUG && OUTRA_SITUACAO)
         Console.WriteLine("Código definido para DEBUG e OUTRA_SITUACAO ");
      #else
         Console.WriteLine("Código não definido nem para DEBUG nem para OUTRA_SITUACAO ");
      #endif
   }
}

Repare que fizemos uso de outra diretiva (#define) que explicaremos mais adiante e de alguns operadores. Os operadores permitidos nas expressões de pré-processamento são: !, ==, !=, && e ||.

As diretivas #define e #undef definem e “indefinem” um identificador dentro do escopo de um arquivo. Se um identificador for definido ele é semanticamente equivalente a true; se for indefinido ele é semanticamente equivalente a false.

Assim podemos deduzir que a saída do código acima será:

Código definido para DEBUG e OUTRA_SITUACAO.

Se o início do código estive assim:

#define DEBUG
#undef OUTRA_SITUACAO

A saída seria:

Código definido para DEBUG.

E só teríamos compilado código que estivessem definidos para DEBUG.

A diretiva #error permite que o código reporte as condições de erro ao compilador.

Por exemplo, no código já mostrado vamos supor que não seja permitido gerar um código tanto para DEBUG quanto para OUTRA_SITUACAO, assim o código poderia ser reescrito como:

#define DEBUG
#define OUTRA_SITUACAO
using System;

public class ClasseExemplo 
{
   public static void Main() 
   {
      #if (DEBUG && ! OUTRA_SITUACAO)
         Console.WriteLine("Código definido para DEBUG");
      #elif (!DEBUG && OUTRA_SITUACAO)
         Console.WriteLine("Código definido para OUTRA_SITUACAO ");
      #elif (DEBUG && OUTRA_SITUACAO)
         Console.WriteLine("Código definido para DEBUG e OUTRA_SITUACAO ");
         #error Tanto o DEBUG quanto OUTRA_SITUACAO estão definidos
      #else
         Console.WriteLine("Código não definido nem para DEBUG nem para OUTRA_SITUACAO ");
      #endif
   }
}

Repare que não há uso do “;” ao final da linha.

A diretiva #warning funciona de forma parecida com a diretiva #error porém ela gera um aviso e não um erro. A diferença é que com a diretiva #warning é gerado um aviso, porém o processamento continua, enquanto que com a diretiva #error o processamento é finalizado.

A diretiva #line permite que se altere o número da linha e o nome do arquivo fonte usado pelo compilador na saída. Se não houver nenhuma diretiva deste tipo, o número de linha e o nome do arquivo são determinados pelo compilador automaticamente.

Vamos ver o seguinte exemplo. Se tentarmos compilar o seguinte código:

class TesteDiretiva
{
	static void Main()
	{
		intt i;
	}
}

Obteremos o seguinte erro:

“The type or namespace name 'intt' could not be found (are you missing a using directive or an 
assembly reference?)” – Line 5

Agora se tentarmos compilar o seguinte código:

class TesteDiretiva
{
	static void Main()
	{
		#line 156 
		intt i;   
	}
}

Obteremos o seguinte erro:

“The type or namespace name 'intt' could not be found (are you missing a using directive or an 
assembly reference?)” – Line 156.

Reparou na mudança do número de Linha?

As diretivas #region e #endregion não possuem nenhum significado semântico ao compilador, elas servem para incluir uma região dentro do código, facilitando a vida do programador, podendo este visualizar apenas os códigos de seu interesse no momento. Estas diretivas servem também para marcar um trecho do código.

Repare no seu uso nas figuras seguintes:

Cc564864.diretivas1(pt-br,MSDN.10).gif

Fig. 1 Uso do #region e #endregion em um código expandido

Cc564864.diretivas2(pt-br,MSDN.10).gif

Fig. 2 Uso do #region e #endregion em um código contraído

Conclusão:

O uso das diretivas pode ajudar a eliminar ou incluir código em seu arquivo fonte, reportar erros e avisos que se integrem aos erros e avisos padrão em tempo de compilação ou delimitar trechos de código que facilitem ao desenvolvedor a sua programação. Faça bom uso delas e boa programação.