Freigeben über


Compilerdirektiven

Dieses Thema beschreibt Compilerdirektiven. Informationen zu Directives von F# Interactive (dotnet fsi) finden Sie unter Interaktive Programmierung mit F#.

Eine Compilerdirektive wird dem Symbol #vorangestellt und wird in einer Zeile selbst angezeigt.

In der folgenden Tabelle sind die Compilerdirektiven aufgeführt, die in F# verfügbar sind.

Directive Description
#if wenn-Ausdruck Unterstützt die bedingte Kompilierung. Code im Abschnitt nach dem #if wird enthalten, wenn der If-Ausdruck zu defined ausgewertet wird (siehe unten).
#else Unterstützt die bedingte Kompilierung. Markiert einen Codeabschnitt, der eingeschlossen werden soll, wenn das mit dem vorherigen #if verwendete Symbol nicht zu defined ausgewertet wird.
#endif Unterstützt die bedingte Kompilierung. Markiert das Ende eines bedingten Codeabschnitts.
#[Zeile] int,
#[Zeile] int-Zeichenfolge,
#[Zeile] intverbatim-string
Gibt die ursprüngliche Quellcodezeile und den Dateinamen für das Debuggen an. Diese Funktion wird für Tools bereitgestellt, die F#-Quellcode generieren.
#nowarn warningcodes Deaktiviert eine oder mehrere Compilerwarnungen, wie durch Warnungscodes angegeben (siehe unten).
#warnon warningcodes Aktiviert eine oder mehrere Compilerwarnungen, wie durch Warnungscodes angegeben (siehe unten).

Anweisungen für die bedingte Kompilierung

Der durch eine dieser Anweisungen deaktivierte Code wird im Visual Studio Code-Editor abgeblendet angezeigt.

Im folgenden Code wird die Verwendung der Anweisungen #if, #else und #endif veranschaulicht. In diesem Beispiel enthält der Code zwei Versionen der Definition von function1. Wenn VERSION1 mithilfe der Option -define compiler definiert wird, wird der Code zwischen den Anweisungen #if und #else aktiviert. Andernfalls wird der Code zwischen #else und #endif aktiviert.

#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

Die #if Direktive akzeptiert auch logische Ausdrücke:

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

Die folgenden Ausdrücke können verwendet werden.

wenn-Ausdruck Auswertung
if-expr1 \|\| if-expr2 defined wenn if-expr1 oder if-expr2 ist defined.
if-expr1 && if-expr2 defined wenn if-expr1 und if-expr2defined sind.
!if-expr1 defined wenn if-expr1 nicht defined.
( if-expr1 ) definiert, wenn if-expr1 definiert ist.
symbol defined wenn es als durch die -define Compileroption definiert markiert ist.

Die logischen Operatoren haben die übliche logische Rangfolge.

In F# gibt es keine #define Compilerdirektive. Sie müssen die Compileroption oder Projekteinstellungen verwenden, um die durch die #if-Direktive verwendeten Symbole zu definieren.

Direktiven für die bedingte Kompilierung können geschachtelt werden. Die Einrückung ist für Compilerdirektiven nicht von Bedeutung.

Vordefinierte Symbole

Der F#-Compiler und das Buildsystem definieren automatisch mehrere Symbole, die für die bedingte Kompilierung verwendet werden können.

Buildkonfigurationssymbole

Die folgenden Symbole werden basierend auf Ihrer Buildkonfiguration definiert:

  • DEBUG: Definiert beim Kompilieren im Debugmodus. Im Projektsystem wird das DEBUG Symbol automatisch in der Debugkonfiguration, aber nicht in der Releasekonfiguration definiert. Dieses Symbol wird häufig mit Assertionen und Diagnosecode verwendet. Weitere Informationen finden Sie unter Assertionen.
  • TRACE: Definiert für Builds, die die Ablaufverfolgung aktivieren. Wie DEBUGfolgt, wird dieses Symbol in der Regel in Debugkonfigurationen definiert, kann aber auch in Releasekonfigurationen aktiviert werden.

Sie können diese Werte überschreiben, indem Sie die -define Compileroption oder Projekteinstellungen verwenden.

Symbole für den Kompilierungsmodus

Die folgenden Symbole unterscheiden zwischen verschiedenen Kompilierungsmodi:

  • COMPILED: Definiert beim Kompilieren von Code mit dem F#-Compiler. Dieses Symbol ist nützlich, wenn Sie Code benötigen, um sich in kompilierten Assemblys anders zu verhalten als bei interaktiven F#-Sitzungen.
  • INTERACTIVE: Definiert beim Kompilieren oder Ausführen von Code in F# Interactive (dotnet fsi), einschließlich interaktiver Sitzungen und Skriptausführung. Auf diese Weise können Sie Code schreiben, der bei der interaktiven Ausführung anders funktioniert.

Weitere Informationen zur Verwendung dieser Symbole in Skripts finden Sie unter "Interaktive Programmierung mit F#".

Beispiel:

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

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

Zielframeworksymbole

Das Buildsystem definiert außerdem Präprozessorsymbole für verschiedene Zielframeworks in SDK-Formatprojekten. Diese Symbole sind hilfreich beim Erstellen von Bibliotheken oder Anwendungen, die auf mehrere .NET-Versionen abzielen.

Zielframeworks Symbole Zusätzliche Symbole
(verfügbar in SDKs für .NET 5 und höher)
Plattformsymbole (nur verfügbar,
wenn Sie einen betriebssystemspezifischen TFM angeben)
.NET Framework NETFRAMEWORK, NET481, , NET48, NET472, NET471, NET47NET462NET461NET46NET452NET451NET45NET40NET35NET20 NET48_OR_GREATER, NET472_OR_GREATER, , NET471_OR_GREATER, NET47_OR_GREATER, NET461_OR_GREATERNET462_OR_GREATER, NET46_OR_GREATER, , NET452_OR_GREATER, NET451_OR_GREATER, , NET45_OR_GREATERNET40_OR_GREATER, , NET35_OR_GREATERNET20_OR_GREATER
.NET Standard NETSTANDARD, NETSTANDARD2_1, , NETSTANDARD1_6NETSTANDARD2_0, NETSTANDARD1_5, NETSTANDARD1_4, NETSTANDARD1_3, , , NETSTANDARD1_2, , NETSTANDARD1_1NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATER, NETSTANDARD1_6_OR_GREATERNETSTANDARD1_5_OR_GREATER, NETSTANDARD1_4_OR_GREATER, NETSTANDARD1_3_OR_GREATER, NETSTANDARD1_2_OR_GREATER, NETSTANDARD1_1_OR_GREATERNETSTANDARD1_0_OR_GREATER
.NET 5 oder höher (und .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_GREATER, NET5_0_OR_GREATERNET6_0_OR_GREATER, NETCOREAPP3_1_OR_GREATER, , NETCOREAPP3_0_OR_GREATER, NETCOREAPP2_2_OR_GREATER, , NETCOREAPP2_1_OR_GREATERNETCOREAPP2_0_OR_GREATER, , NETCOREAPP1_1_OR_GREATERNETCOREAPP1_0_OR_GREATER ANDROID, BROWSER, IOS, MACCATALYST, MACOS, TVOS, WINDOWS
[OS][version] (z. B. IOS15_1),
[OS][version]_OR_GREATER (z. B. IOS15_1_OR_GREATER)

Hinweis

  • Versionslose Symbole werden unabhängig von der Version definiert, die Sie als Ziel verwenden.
  • Versionsspezifische Symbole werden nur für die Version definiert, die Sie als Ziel verwenden.
  • Die <framework>_OR_GREATER-Symbole werden für die Zielversion und alle früheren Versionen definiert. Wenn Sie beispielsweise .NET Framework 2.0 als Ziel festgelegt haben, werden die folgenden Symbole definiert: NET20, NET20_OR_GREATER, NET11_OR_GREATER und NET10_OR_GREATER.
  • Die NETSTANDARD<x>_<y>_OR_GREATER-Symbole werden nur für .NET Standard-Ziele definiert und nicht für Ziele, die .NET Standard implementieren, z. B. .NET Core und .NET Framework.
  • Diese unterscheiden sich von den Zielframeworkmonikern (TFMs), die von der TargetFramework-Eigenschaft von MSBuild und NuGet verwendet werden.

Sie können z. B. diese Symbole verwenden, um Code basierend auf dem Zielframework bedingt zu kompilieren:

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

NULLABLE-Direktive

Ab F# 9 können Sie nullbare Referenztypen im Projekt aktivieren:

<Nullable>enable</Nullable>

Dadurch wird automatisch die Direktive NULLABLE für den Build festgelegt. Während der anfänglichen Einführung des Features ist es nützlich, widersprüchlichen Code bei Bedarf durch #if NULLABLE-Hash-Direktiven zu ändern.

#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

Zeilendirektiven

Beim Erstellen meldet der Compiler Fehler im F#-Code durch das Referenzieren von Zeilennummern, in denen die jeweiligen Fehler auftreten. Diese Zeilennummern beginnen bei 1 für die erste Zeile in einer Datei. Wenn Sie jedoch F#-Quellcode aus einem anderen Tool generieren, sind die Zeilennummern im generierten Code im Allgemeinen nicht relevant, da die Fehler im generierten F#-Code höchstwahrscheinlich auf eine andere Quelle zurückgehen. Mit der #line-Direktive können Autoren von Tools, die F#-Quellcode generieren, Informationen über die ursprünglichen Zeilennummern und Quelldateien an den generierten F#-Code weitergeben.

Beim Verwenden der #line-Anweisung müssen Dateinamen in Anführungszeichen gesetzt werden. Sofern das verbatim-Token (@) nicht am Anfang der Zeichenfolge angezeigt wird, müssen Sie umgekehrte Schrägstriche durch die Verwendung von zwei (und nicht nur einem) umgekehrten Schrägstrichen escapen, um sie im Pfad zu verwenden. Im Folgenden finden Sie gültige Zeilentoken. In diesen Beispielen wird davon ausgegangen, dass die ursprüngliche Script1-Datei in einer automatisch generierten F#-Codedatei resultiert, wenn er über ein Tool ausgeführt wird, und dass der Code am Speicherort dieser Direktiven aus einigen Token in Zeile 25 in der Datei Script1 generiert wird.

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

Diese Token geben an, dass der an diesem Speicherort generierte F#-Code aus einigen Konstrukten in oder in der Nähe der Zeile 25 in Script1 abgeleitet ist.

Beachten Sie, dass #line Direktiven keinen Einfluss auf das Verhalten von #nowarn / #warnon haben. Diese beiden Direktiven beziehen sich immer auf die Datei, die kompiliert wird.

Richtlinien warnen

Warndirektiven deaktivieren oder aktivieren angegebene Compilerwarnungen für Teile einer Quelldatei.

Eine Warndirektive ist eine einzelne Zeile Quellcode, die aus

  • Optionales führendes Leerzeichen
  • Die Zeichenfolge #nowarn oder #warnon
  • Whitespace
  • Mindestens einige Warncodes (siehe unten), getrennt durch Leerzeichen
  • Optionale Leerzeichen
  • Optionaler Zeilenkommentar

Ein Warncode ist eine Folge von Ziffern (die die Warnnummer darstellt), die optional von FSdoppelten Anführungszeichen umgeben ist.

Eine #nowarn Direktive deaktiviert eine Warnung, bis eine #warnon Direktive für dieselbe Warnnummer gefunden wird oder bis zum Ende der Datei. Ebenso deaktiviert eine #nowarn Direktive eine Warnung, bis eine #warnon Direktive für dieselbe Warnungsnummer gefunden wurde oder bis zum Ende der Datei. Vor und nach solchen Paaren gilt die Standardeinstellung für die Kompilierung.

  • keine Warnung, wenn sie durch eine Compileroption --nowarn (oder die entsprechende msbuild-Eigenschaft) deaktiviert ist
  • keine Warnung für Opt-In-Warnungen, es sei denn, dies ist durch die Compileroption --warnon (oder die entsprechende msbuild-Eigenschaft) aktiviert.

Nachfolgend sehen Sie ein konstruiertes Beispiel.

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

Siehe auch