共用方式為


編譯程式指示詞

本主題描述編譯程式指示詞,適用於 F# Interactive (dotnet fsi) 指示詞,請參閱 使用 F# 進行互動式程式設計

編譯程式指示詞前面會加上 # 符號,並單獨出現在行上。

下表列出 F# 中可用的編譯程式指示詞。

Directive Description
#if if運算式 支援條件式編譯。 #if區段中的程式代碼將被包含在內,如果if-expression的評估結果為defined
#else 支援條件式編譯。 如果與前面的 #if 一起使用的符號不評估為 defined,則標記代碼區段以包含。
#endif 支援條件式編譯。 標示程式碼的條件式區段結尾。
#[line] int
#[line] intstring
#[line] int逐字字串
表示原始的原始程式碼行和檔案名稱 (適用於偵錯)。 這項功能提供用於產生 F# 原始程式碼的工具。
#nowarn 警告代碼 停用一或多個編譯程式警告,如 warningcodes 所指定(請參閱下文)。
#warnon 警告代碼 啟用一或多個編譯程式警告,如 warningcodes 所指定(請參閱下文)。

條件式編譯指示詞

由上述其中一個指示詞停用的程式碼會在 Visual Studio 程式碼編輯器中顯示為停用。

下列程式碼說明如何使用 #if#else#endif 指示詞。 在此範例中,程式碼包含兩個版本的 function1 定義。 使用 VERSION1定義 時,會啟用 #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-expr1if-expr2 為 ,則為 defined
if-expr1 && if-expr2 defined 如果 if-expr1if-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 版本為目標的程式庫或應用程式時很有用。

目標框架 符號 其他符號
(適用於 .NET 5+ SDK)
平台符號(僅可用於特定情境)
當您指定作業系統特定的 TFM 時
.NET Framework NETFRAMEWORKNET481NET48NET472NET471NET47NET462NET461NET46NET452NET451NET45NET40NET35NET20 NET48_OR_GREATERNET472_OR_GREATERNET471_OR_GREATERNET47_OR_GREATERNET462_OR_GREATERNET461_OR_GREATERNET46_OR_GREATERNET452_OR_GREATERNET451_OR_GREATERNET45_OR_GREATERNET40_OR_GREATERNET35_OR_GREATERNET20_OR_GREATER
.NET Standard NETSTANDARDNETSTANDARD2_1NETSTANDARD2_0NETSTANDARD1_6NETSTANDARD1_5NETSTANDARD1_4NETSTANDARD1_3NETSTANDARD1_2NETSTANDARD1_1NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATERNETSTANDARD2_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) NETNET10_0NET9_0NET8_0NET7_0NET6_0NET5_0NETCOREAPPNETCOREAPP3_1NETCOREAPP3_0NETCOREAPP2_2NETCOREAPP2_1NETCOREAPP2_0NETCOREAPP1_1NETCOREAPP1_0 NET10_0_OR_GREATERNET9_0_OR_GREATERNET8_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 ANDROIDBROWSERIOSMACCATALYSTMACOSTVOS、、、 WINDOWS
[OS][version] (例如 IOS15_1)、
[OS][version]_OR_GREATER (例如 IOS15_1_OR_GREATER)

備註

  • 無論您的目標版本為何,系統都會定義無版本符號。
  • 系統只會針對您設定為目標的版本定義版本特定符號。
  • 系統會針對您的目標版本和所有更早版本定義 <framework>_OR_GREATER 符號。 舉例來說,如果您要以 .NET Framework 2.0 為目標,則會定義下列符號:NET20NET20_OR_GREATERNET11_OR_GREATERNET10_OR_GREATER
  • NETSTANDARD<x>_<y>_OR_GREATER 符號只會針對 .NET Standard 目標定義,而不是針對實作 .NET Standard 的目標,例如 .NET Core 和 .NET Framework。
  • 這些與 MSBuild TargetFramework 屬性NuGet 使用的目標框架標記不同。

例如,您可以使用這些符號,根據目標架構有條件地編譯程式碼:

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

NULLABLE 指示詞

從 F# 9 開始,您可以在專案中啟用可空的參考類型。

<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

行指示詞

建置時,編譯器會參考發生的每個錯誤所在的行號,以報告 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# 程式碼,是衍生自 25Script1 行或附近的某些建構。

請注意,#line 指示詞不會影響#nowarn / #warnon 的行為。 這兩個指示詞一律會關聯正在編譯的檔案。

Warn 指示詞

警告指示詞會停用或啟用來源檔案部分的指定編譯程式警告。

warn 指示詞是由單一行原始程式碼組成的

  • 選擇性前置空格符
  • 字串 #nowarn#warnon
  • Whitespace
  • 一或多個 警告碼 (如下所示),以空格符分隔
  • 選擇性空格符
  • 選擇性行註解

warningcode 是一連串的數位(代表警告編號),在 前面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

另請參閱