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


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

В этом разделе описываются директивы компилятора для директив 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.

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

Директива 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

См. также