Поделиться через


Директивы компилятора

В этом разделе описываются директивы компилятора для директив F# Interactive (dotnet fsi) см. статью "Интерактивное программирование с помощью F#".

Директива компилятора префиксируется символом #и отображается в строке.

В следующей таблице перечислены директивы компилятора, доступные в F#.

Directive Description
#if if-expression Поддерживает условную компиляцию. Код в разделе после #if включён, если выражение if оценивается как defined (см. ниже).
#else Поддерживает условную компиляцию. Отмечает раздел кода для включения, если символ, используемый с предыдущим #if, не соответствует defined.
#endif Поддерживает условную компиляцию. Помечает конец условного раздела кода.
#[строка] int,
#[строка] intstring,
#[строка] intverbatim-string
Указывает исходную строку кода и имя файла для отладки. Эта возможность предназначена для средств, создающих исходный код F#.
#nowarn коды предупреждений Отключает одно или несколько предупреждений компилятора, указанных в кодах предупреждений (см. ниже).
#warnon коды предупреждений Включает одно или несколько предупреждений компилятора, указанных в кодах предупреждений (см. ниже).

Директивы условной компиляции

Код, деактивированный одной из этих директив, отображается неактивным в редакторе Visual Studio Code.

В следующем коде демонстрируется применение директив #if, #else и #endif. В данном примере код содержит две версии определения function1. При VERSION1 определении с помощью параметра компилятора -define код между #if директивой и #else директивой активируется. В противном случае активируется код между директивами #else и #endif.

#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

Директива #if также принимает логические выражения:

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

Можно использовать следующие выражения.

if-expr оценка
if-expr1 \|\| if-expr2 defined если if-expr1 или if-expr2defined.
if-expr1 && if-expr2 defined если if-expr1 и if-expr2 являются defined.
!if-expr1 defined если if-expr1 не defined.
( if-expr1 ) определяется, если if-expr1 определен.
symbol defined если указано как определено параметром компилятора -define.

Логические операторы имеют обычный логический приоритет.

В F# отсутствует директива компилятора #define. Вы должны использовать параметр компилятора или параметры проекта для определения символов, используемых директивой #if.

Директивы условной компиляции не могут быть вложенными. Отступ не имеет значения для директив компилятора.

Стандартные символы

Компилятор F# и система сборки автоматически определяют несколько символов, которые можно использовать для условной компиляции.

Символы конфигурации сборки

Следующие символы определяются на основе конфигурации сборки:

  • DEBUG: определяется при компиляции в режиме отладки. В системе DEBUG проекта символ автоматически определяется в конфигурации отладки, но не в конфигурации выпуска. Этот символ часто используется с утверждениями и диагностическим кодом. Дополнительные сведения см. в разделе "Утверждения".
  • TRACE: определено для сборок, которые обеспечивают трассировку. Например DEBUG, этот символ обычно определяется в конфигурациях отладки, но также может быть включен в конфигурациях выпуска.

Эти значения можно переопределить с помощью -define параметра компилятора или параметров проекта.

Символы режима компиляции

Следующие символы различаются между различными режимами компиляции:

  • COMPILED: определяется при компиляции кода с помощью компилятора F#. Этот символ полезен, если вам нужен код для поведения по-разному в скомпилированных сборках и интерактивных сеансах F#.
  • INTERACTIVE: определяется при компиляции или выполнении кода в F# Interactive (dotnet fsi), включая интерактивные сеансы и выполнение скрипта. Это позволяет писать код, который работает по-разному при интерактивном выполнении.

Дополнительные сведения об использовании этих символов в скриптах см. в статье "Интерактивное программирование с помощью F#".

Пример:

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

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

Символы целевой платформы

Система сборки также определяет символы препроцессора для различных целевых платформ в проектах в стиле ПАКЕТА SDK. Эти символы полезны при создании библиотек или приложений, предназначенных для нескольких версий .NET.

Целевые фреймворки Символы Дополнительные символы
(доступно в пакетах SDK для .NET 5 и более поздних версий)
Символы платформы (доступны только
при указании TFM для конкретной ОС)
Платформа .NET Framework NETFRAMEWORK NET481, NET48NET472NET471NET47NET462NET461NET46NET452NET451NET45NET40NET35NET20 NET48_OR_GREATER, NET472_OR_GREATER, NET471_OR_GREATERNET47_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_0NETSTANDARD1_6NETSTANDARD1_5NETSTANDARD1_4NETSTANDARD1_3NETSTANDARD1_2NETSTANDARD1_1NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATERNETSTANDARD1_6_OR_GREATERNETSTANDARD1_5_OR_GREATERNETSTANDARD1_4_OR_GREATERNETSTANDARD1_3_OR_GREATERNETSTANDARD1_2_OR_GREATERNETSTANDARD1_1_OR_GREATERNETSTANDARD1_0_OR_GREATER
.NET 5+ (и .NET Core) NET NET10_0, NET9_0NET8_0NET7_0NET6_0NET5_0NETCOREAPPNETCOREAPP3_1NETCOREAPP3_0NETCOREAPP2_2NETCOREAPP2_1NETCOREAPP2_0NETCOREAPP1_1NETCOREAPP1_0 NET10_0_OR_GREATER, NET9_0_OR_GREATER, NET8_0_OR_GREATERNET7_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, IOSMACCATALYSTMACOSTVOSWINDOWS
[OS][version] (например IOS15_1),
[OS][version]_OR_GREATER (например IOS15_1_OR_GREATER)

Замечание

  • Символы без привязки к версии определены независимо от версии, которую вы хотите использовать в качестве целевой.
  • Символы, специфичные для версии, определены только для той версии, на которую вы нацеливаетесь.
  • Символы <framework>_OR_GREATER определены для версии, которую вы хотите использовать в качестве целевой, и всех более ранних версий. Например, если вы выбрали .NET Framework 2.0, определяются следующие символы: NET20, NET20_OR_GREATER, NET11_OR_GREATER и NET10_OR_GREATER.
  • NETSTANDARD<x>_<y>_OR_GREATER Символы определяются только для целевых объектов .NET Standard, а не для целевых объектов, реализующих .NET Standard, таких как .NET Core и платформа .NET Framework.
  • Они отличаются от моникеров целевой платформы (TFM), используемых свойством TargetFramework и NuGet.

Например, эти символы можно использовать для условной компиляции кода на основе целевой платформы:

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

Директива NULLABLE

Начиная с F# 9, в проекте можно включить ссылочные типы, допускающие значение NULL:

<Nullable>enable</Nullable>

Это автоматически устанавливает директиву NULLABLE в сборке. Это полезно при первоначальном развертывании функции, чтобы условно изменить конфликтующий код с помощью директив хэша #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

Директивы line

При сборке компилятор сообщает об ошибках в коде F #, ссылаясь на номера строк, в которых возникли ошибки. Номера строк начинаются с 1 для первой строки в файле. Тем не менее при создании исходного кода F# из другого средства номера строк в сформированном коде обычно не представляют интереса, поскольку ошибки в сформированном коде F#, скорее всего, проистекают из другого источника. Директива #line позволяет разработчикам средств, формирующих исходный код F#, передавать сведения о номерах исходных строк и исходных файлах в сформированный код F#.

При использовании директивы #line необходимо заключать имена файлов в кавычки. Если в начале строки не указывается токен verbatim (@), то чтобы использовать в пути символы обратной косой черты, необходимо их экранировать, указывая две обратные косые черты вместо одной. Далее приводятся допустимые токены строк. В этих примерах предполагается, что исходный файл Script1 при запуске в соответствующем средстве приводит к автоматическому созданию файла кода F# и что код в месте расположения этих директив формируется из некоторых токенов в строке 25 файла Script1.

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

Эти токены указывают, что код F#, сформированный в этом месте, является производным от некоторых конструкций в строке 25 или рядом с ней в файле Script1.

Обратите внимание, что #line директивы не влияют на поведение #nowarn / #warnon. Эти две директивы всегда связаны с скомпилированным файлом.

Директивы Warn

Директивы Warn отключают или включают указанные предупреждения компилятора для определённых частей исходного файла.

Директива warn — это одна строка исходного кода, состоящая из

  • Необязательные начальные пробелы
  • Строка #nowarn или #warnon
  • Whitespace
  • Один или несколько кодов предупреждений (см. ниже), разделенных пробелами
  • Необязательное пробелы
  • Необязательный строковый комментарий

Код предупреждения — это последовательность цифр (представляющая номер предупреждения), которая при необходимости может начинаться с FS и при необходимости может быть окружена двойными кавычками.

#nowarn Директива отключает предупреждение до тех пор, пока не будет найдена #warnon директива для того же номера предупреждения, либо до конца файла. Аналогичным образом, #nowarn директива отключает предупреждение до тех пор, пока не будет найдена #warnon директива для одного и того же номера предупреждения или до конца файла. До и после таких пар применяется компиляция по умолчанию.

  • Нет предупреждений, если они отключены с помощью параметра компилятора --nowarn (или соответствующего свойства MSBuild)
  • нет предупреждений о предупреждениях при согласии, если не включен параметр компилятора --warnon (или соответствующее свойство msbuild)

Вот (выдуманный) пример.

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

См. также