编译器指令

本主题介绍处理器指令和编译器指令。

若要了解 F# 交互窗口 (dotnet fsi) 指令,请参阅使用 F# 进行交互式编程

预处理器指令

预处理器指令以 # 符号作为前缀,出现在行本身上。 它由预处理器进行解释,后者在编译器本身之前运行。

下表列出了 F# 中可用的预处理器指令。

指令 描述
#if符号 支持条件编译。 如果定义了符号,则包含 #if 后面部分中的代码。 符号也可以用 ! 求反。
#else 支持条件编译。 如果未定义与前面的 #if 一起使用的符号,则将一段代码标记为包含在内。
#endif 支持条件编译。 标记条件代码段的末尾。
#[line] int,
#[line] intstring,
#[line] intverbatim-string
指示原始源代码行和文件名以用于调试。 此功能是为生成 F# 源代码的工具而提供的。
#nowarnwarningcode 禁用编译器警告。 若要禁用警告,请在编译器输出中查找其编号,然后将它包含在引号内。 省略“FS”前缀。 若要禁用同一行上的多个警告编号,请将每个编号用引号引起来,并使用空格分隔每个字符串。
例如:#nowarn "9" "40"

禁用警告的效果会应用于整个文件,包括位于该指令之前文件部分。|

条件编译指令

由这些指令之一停用的代码会在 Visual Studio Code 编辑器中显示为灰色。

注意

条件编译指令的行为与它在其他语言中的行为不同。 例如,不能使用涉及符号的布尔表达式,并且 truefalse 没有特殊含义。 在 if 指令中使用的符号必须通过命令行或在项目设置中定义;没有 define 预处理器指令。

以下代码演示了 #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

F# 中没有 #define 预处理器指令。 必须使用编译器选项或项目设置来定义 #if 指令使用的符号。

条件编译指令可以进行嵌套。 缩进对于预处理器指令并不重要。

也可以使用 ! 对符号求反。 此示例中,字符串的值只有在非调试时才有意义:

#if !DEBUG
let str = "Not debugging!"
#else
let str = "Debugging!"
#endif

行指令

在生成时,编译器会通过引用每个错误发生时所在的行号来报告 F# 代码中的错误。 这些行号从 1 开始(表示文件中的第一行)。 但是,如果要从另一种工具生成 F# 源代码,则生成的代码中的行号通常没什么意义,因为生成的 F# 代码中的错误很可能是由其他来源导致的。 #line 指令提供了一种方法,使生成 F# 源代码的工具的作者可以将有关原始行号和源文件的信息传递给生成的 F# 代码。

使用 #line 指令时,必须将文件名括在引号内。 除非原义标记 (@) 出现在字符串前面,否则必须使用两个反斜杠字符(而不是一个)对反斜杠字符进行转义,才能在路径中使用它们。 以下是有效的行标记。 在这些示例中,假设原始文件 Script1 会在通过某种工具运行时产生自动生成的 F# 代码文件,并且这些指令的位置处的代码是从文件 Script1 中第 25 行处的一些标记生成的。

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

这些标记指示在此位置生成的 F# 代码派生自位于 Script1 中第 25 行上或附近的一些构造。

另请参阅