Partilhar via


Diretivas do compilador

Este tópico descreve diretivas de compilador, para diretivas F# Interactive (dotnet fsi), consulte Programação interativa com F#.

Uma diretiva de compilador é prefixada com o símbolo # e aparece em uma linha por si só.

A tabela a seguir lista as diretivas do compilador que estão disponíveis em F#.

Directive Description
#if se-expressão Suporta compilação condicional. Código na seção após o #if é incluído se a instrução if resultar em defined (veja abaixo).
#else Suporta compilação condicional. Marca uma seção de código para ser incluída se o símbolo previamente utilizado com #if não for avaliado como defined.
#endif Suporta compilação condicional. Marca o fim de uma seção condicional do código.
#[linha] int,
#[linha] int string,
#[linha] int verbatim-string
Indica a linha do código-fonte original e o nome do arquivo, para depuração. Esse recurso é fornecido para ferramentas que geram código-fonte F#.
#nowarn códigos de advertência Desativa um ou mais avisos do compilador conforme especificado pelos códigos de aviso (veja abaixo).
#warnon códigos de advertência Permite um ou mais avisos do compilador, conforme especificado pelos códigos de aviso (veja abaixo).

Diretivas de compilação condicional

O código desativado por uma dessas diretivas aparece esmaecido no Editor de Códigos do Visual Studio.

O código a seguir ilustra o uso das #ifdiretivas , #elsee #endif . Neste exemplo, o código contém duas versões da definição de function1. Quando VERSION1 é definido usando a opção de compilador -define, o código entre a #if diretiva e a #else diretiva é ativado. Caso contrário, o código entre #else e #endif é ativado.

#if VERSION1
let function1 x y =
   printfn "x: %d y: %d" x y
   x + 2 * y
#else
let function1 x y =
   printfn "x: %d y: %d" x y
   x - 2*y
#endif

let result = function1 10 20

A #if diretiva aceita igualmente expressões lógicas:

#if SILVERLIGHT || COMPILED && (NETCOREFX || !DEBUG)
#endif

As seguintes expressões podem ser usadas.

IF-EXPR avaliação
if-expr1 \|\| if-expr2 defined se if-expr1 ou if-expr2 é defined.
if-expr1 && if-expr2 defined se if-expr1 e if-expr2 são defined.
!if-expr1 defined se if-expr1 não é defined.
( if-expr1 ) definido se if-expr1 está definido.
symbol defined se for marcado conforme definido pela opção de compilador -define.

Os operadores lógicos têm a precedência lógica usual.

Não há nenhuma #define diretiva de compilador em F#. Você deve usar a opção do compilador ou as configurações do projeto para definir os símbolos usados pela #if diretiva.

As diretivas de compilação condicional podem ser aninhadas. A indentação não é significativa para diretivas de compilador.

Símbolos predefinidos

O compilador F# e o sistema de compilação definem automaticamente vários símbolos que podem ser usados para compilação condicional.

Símbolos de configuração de compilação

Os seguintes símbolos são definidos com base na sua configuração de compilação:

  • DEBUG: Definido ao compilar no modo de depuração. No sistema de projeto, o DEBUG símbolo é definido automaticamente na configuração Debug, mas não na configuração Release. Este símbolo é comumente usado com asserções e código de diagnóstico. Para obter mais informações, consulte Asserções.
  • TRACE: Definido para compilações que permitem o rastreamento. Como DEBUG, este símbolo é normalmente definido em configurações de depuração, mas também pode ser ativado em configurações de versão.

Você pode substituir esses valores usando a opção do compilador ou as configurações do-define projeto.

Símbolos do modo de compilação

Os seguintes símbolos distinguem entre diferentes modos de compilação:

  • COMPILED: Definido ao compilar código com o compilador F#. Esse símbolo é útil quando você precisa que o código se comporte de forma diferente em assemblies compilados versus sessões interativas em F#.
  • INTERACTIVE: Definido ao compilar ou executar código em F# Interactive (dotnet fsi), incluindo sessões interativas e execução de script. Isso permite que você escreva código que funciona de forma diferente ao executar interativamente.

Para obter mais informações sobre como usar esses símbolos em scripts, consulte Programação interativa com F#.

Exemplo:

#if INTERACTIVE
// Code specific to F# Interactive
#r "nuget: Newtonsoft.Json"
#endif

#if COMPILED
// Code specific to compiled assemblies
open System.Configuration
#endif

Símbolos da estrutura de destino

O sistema de compilação também define símbolos de pré-processador para diferentes estruturas de destino em projetos no estilo SDK. Esses símbolos são úteis ao criar bibliotecas ou aplicativos destinados a várias versões do .NET.

Estruturas de destino Symbols Símbolos adicionais
(disponível em SDKs do .NET 5+)
Símbolos da plataforma (disponível apenas
quando você especifica um TFM específico do sistema operacional)
.NET Framework NETFRAMEWORK, NET481, , NET48, NET472, NET471, NET47NET462NET461NET46NET452NET451NET45NET40NET35NET20 NET48_OR_GREATER, NET472_OR_GREATER, , NET471_OR_GREATER, , NET47_OR_GREATERNET462_OR_GREATERNET461_OR_GREATERNET46_OR_GREATERNET452_OR_GREATERNET451_OR_GREATERNET45_OR_GREATERNET40_OR_GREATERNET35_OR_GREATERNET20_OR_GREATER
.NET Standard NETSTANDARD, NETSTANDARD2_1, , NETSTANDARD2_0, NETSTANDARD1_6, NETSTANDARD1_5NETSTANDARD1_4, NETSTANDARD1_3, NETSTANDARD1_2NETSTANDARD1_1,NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATER, NETSTANDARD1_6_OR_GREATER, NETSTANDARD1_5_OR_GREATER, NETSTANDARD1_4_OR_GREATERNETSTANDARD1_3_OR_GREATER, NETSTANDARD1_2_OR_GREATER, NETSTANDARD1_1_OR_GREATER, NETSTANDARD1_0_OR_GREATER
.NET 5+ (e .NET Core) NET, NET10_0, , NET9_0, NET8_0, NET7_0, NET6_0NET5_0NETCOREAPPNETCOREAPP3_1NETCOREAPP3_0NETCOREAPP2_2NETCOREAPP2_1NETCOREAPP2_0NETCOREAPP1_1NETCOREAPP1_0 NET10_0_OR_GREATER, NET9_0_OR_GREATER, , NET8_0_OR_GREATER, , NET7_0_OR_GREATERNET6_0_OR_GREATERNET5_0_OR_GREATERNETCOREAPP3_1_OR_GREATERNETCOREAPP3_0_OR_GREATERNETCOREAPP2_2_OR_GREATERNETCOREAPP2_1_OR_GREATERNETCOREAPP2_0_OR_GREATERNETCOREAPP1_1_OR_GREATERNETCOREAPP1_0_OR_GREATER ANDROID, BROWSER, IOS, MACCATALYST, MACOS, TVOS, WINDOWS
[OS][version] (por exemplo IOS15_1),
[OS][version]_OR_GREATER (por exemplo IOS15_1_OR_GREATER)

Observação

  • Os símbolos sem versão são definidos independentemente da versão que está a ser alvo.
  • Os símbolos específicos de cada versão são definidos apenas para a versão que está a almejar.
  • Os <framework>_OR_GREATER símbolos são definidos para a versão alvo e todas as versões anteriores. Por exemplo, se você estiver direcionando o .NET Framework 2.0, os seguintes símbolos serão definidos: NET20, NET20_OR_GREATER, NET11_OR_GREATERe NET10_OR_GREATER.
  • Os NETSTANDARD<x>_<y>_OR_GREATER símbolos são definidos apenas para destinos .NET Standard e não para destinos que implementam o .NET Standard, como .NET Core e .NET Framework.
  • Eles são diferentes dos identificadores de estrutura de destino (TFMs) usados pela propriedade TargetFramework e NuGet.

Por exemplo, você pode usar esses símbolos para compilar condicionalmente o código com base na estrutura de destino:

#if NET6_0_OR_GREATER
// Use .NET 6+ specific APIs
#else
// Use alternative implementation for older frameworks
#endif

Diretiva NULLABLE

A partir do F# 9, você pode habilitar tipos de referência anuláveis no projeto:

<Nullable>enable</Nullable>

Isso define automaticamente a diretiva NULLABLE para a compilação. Durante a implementação inicial da funcionalidade, é útil alterar condicionalmente o código conflitante por meio de diretivas de hash #if NULLABLE.

#if NULLABLE 
let length (arg: 'T when 'T: not null) =
    Seq.length arg
#else
let length arg =
    match arg with
    | null -> -1
    | s -> Seq.length s
#endif

Diretivas de linha

Ao criar, o compilador relata erros no código F# fazendo referência a números de linha nos quais cada erro ocorre. Esses números de linha começam em 1 para a primeira linha de um arquivo. No entanto, se você estiver gerando código-fonte F# de outra ferramenta, os números de linha no código gerado geralmente não são de interesse, porque os erros no código F# gerado provavelmente surgem de outra fonte. A #line diretiva fornece uma maneira para os autores de ferramentas que geram código-fonte F# para passar informações sobre os números de linha originais e arquivos de origem para o código F# gerado.

Quando você usa a diretiva, os #line nomes de arquivo devem ser colocados entre aspas. A menos que o token literal (@) apareça na frente da cadeia de caracteres, você deve escapar dos caracteres de barra invertida usando dois caracteres de barra invertida em vez de um para usá-los no caminho. A seguir estão os tokens de linha válidos. Nesses exemplos, suponha que o arquivo Script1 original resulta em um arquivo de código F# gerado automaticamente quando ele é executado por meio de uma ferramenta e que o código no local dessas diretivas é gerado a partir de alguns tokens na linha 25 no arquivo Script1.

# 25
#line 25
#line 25 "C:\\Projects\\MyProject\\MyProject\\Script1"
#line 25 @"C:\Projects\MyProject\MyProject\Script1"
# 25 @"C:\Projects\MyProject\MyProject\Script1"

Esses tokens indicam que o código F# gerado neste local é derivado de algumas construções em ou perto da linha 25 em Script1.

Note que as diretivas #line não influenciam o comportamento de #nowarn / #warnon. Estas duas diretivas relacionam-se sempre com o ficheiro que está a ser compilado.

Diretivas de advertência

As diretivas de aviso desabilitam ou habilitam avisos de compilador especificados para partes de um arquivo de origem.

Uma diretiva de aviso é uma única linha de código-fonte que consiste em:

  • Espaço em branco à esquerda opcional
  • A cadeia de caracteres #nowarn ou #warnon
  • Whitespace
  • Um ou mais códigos de aviso (ver abaixo), separados por espaços em branco
  • Espaço em branco opcional
  • Comentário de linha opcional

Um código de aviso é uma sequência de dígitos (representando o número de aviso), opcionalmente precedida por FS, opcionalmente rodeada por aspas duplas.

Uma #nowarn diretiva desativa um aviso até que uma #warnon diretiva para o mesmo número de aviso seja encontrada, ou então até o final do arquivo. Da mesma forma, uma #nowarn diretiva desativa um aviso até que uma #warnon diretiva para o mesmo número de aviso seja encontrada, ou então até o final do arquivo. Antes e depois de tais pares, aplica-se o padrão de compilação, que é

  • nenhum aviso se desativado por uma opção de compilador --nowarn (ou a respetiva propriedade msbuild)
  • Nenhum aviso para avisos de adesão, a menos que seja ativado pela opção do compilador --warnon (ou a respetiva propriedade MSBuild)

Aqui está um exemplo (inventado).

module A
match None with None -> ()     // warning
let x =
    #nowarn 25
    match None with None -> 1  // no warning
    #warnon FS25
match None with None -> ()     // warning
#nowarn "FS25" FS007 "42"
match None with None -> ()     // no warning

Ver também