Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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 dasDEBUGSymbol 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. WieDEBUGfolgt, 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_GREATERundNET10_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
#nowarnoder#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