Freigeben über


C#-Präprozessoranweisungen

Obwohl der Compiler keinen separaten Präprozessor hat, verarbeitet er die in diesem Abschnitt beschriebenen Direktiven so, als ob es einen gab. Verwenden Sie diese Direktiven, um bei der bedingten Kompilierung zu helfen. Sie können diese Anweisungen im Gegensatz zu C- und C++-Anweisungen nicht verwenden, um Makros zu erstellen. Eine Präprozessordirektive muss die einzige Anweisung in einer Zeile sein.

Die C#-Sprachreferenz dokumentiert die zuletzt veröffentlichte Version der C#-Sprache. Außerdem enthält sie erste Dokumentation für Features in der öffentlichen Vorschau für die kommende Sprachversion.

In der Dokumentation werden alle Features identifiziert, die in den letzten drei Versionen der Sprache oder in der aktuellen öffentlichen Vorschau eingeführt wurden.

Tipp

Informationen dazu, wann ein Feature erstmals in C# eingeführt wurde, finden Sie im Artikel zum Versionsverlauf der C#-Sprache.

Dateibasierte Apps

Dateibasierte Apps sind Programme , die Sie kompilieren und ausführen, indem dotnet run Program.cs Sie (oder eine beliebige *.cs Datei) verwenden. Der C#-Compiler ignoriert diese Präprozessordirektiven, aber das Buildsystem analysiert sie, um die Ausgabe zu erzeugen. Diese Direktiven generieren Warnungen, wenn sie in einer projektbasierten Kompilierung auftreten.

Der C#-Compiler ignoriert jede Präprozessordirektive, die mit #: oder #! beginnt.

Die #! Präprozessordirektive ermöglicht Unix-Shells die direkte Ausführung einer C#-Datei mithilfe dotnet runvon . Zum Beispiel:

#!/usr/bin/env dotnet run
Console.WriteLine("Hello");

Der vorangehende Codeausschnitt informiert eine Unix-Shell, die Datei mithilfe dotnet runvon . Der /usr/bin/env Befehl sucht die dotnet ausführbare Datei in Ihrem PATH und macht diesen Ansatz in verschiedenen Unix- und macOS-Verteilungen portierbar. Die #! Zeile muss die erste Zeile in der Datei sein, und die folgenden Token sind das auszuführende Programm. Sie müssen die Ausführungsberechtigung (x) für die C#-Datei für dieses Feature aktivieren.

Die #: Direktiven, die in dateibasierten Apps verwendet werden, werden in der Dateibasierten App-Referenz beschrieben.

Andere Tools können nach der #: Konvention neue Token hinzufügen.

Nullwerte zulassender Kontext

Die #nullable-Präprozessoranweisung setzt die Anmerkungs- und Warnungsflags im Null-Wert-fähigen Kontext. Die Anweisung steuert, ob Nullable-Anmerkungen wirksam sind und ob Warnungen zur NULL-Zulässigkeit angegeben werden. Jedes Flag ist entweder deaktiviert oder aktiviert.

Sie können beide Kontexte auf Projektebene (außerhalb des C#-Quellcodes) angeben, indem Sie das Nullable Element dem PropertyGroup Element hinzufügen. Die #nullable-Anweisung steuert die Anmerkungs- und Warnungsflags und hat Vorrang vor anderen Einstellungen auf Projektebene. Eine Anweisung legt das von ihr gesteuerte Flag fest, bis sie von einer anderen Anweisung überschrieben wird oder bis zum Ende der Quelldatei.

Die Auswirkungen der Anweisungen lauten wie folgt:

  • #nullable disable: Legt den nullfähigen Kontext auf deaktiviert fest.
  • #nullable enable: Legt den nullfähigen Kontext auf aktiviert fest.
  • #nullable restore: Stellt den nullfähigen Warnungskontext auf Projekteinstellungen wieder her.
  • #nullable disable annotations: Setzt das Anmerkungsflag im nullfähigen Kontext auf deaktiviert.
  • #nullable enable annotations: Setzt das Anmerkungsflag im nullfähigen Kontext auf aktiviert.
  • #nullable restore annotations: Stellt das Anmerkungsflag im nullfähigen Kontext auf Projekteinstellungen wieder her.
  • #nullable disable warnings: Setzt das Warnungsflag im nullfähigen Kontext auf deaktiviert.
  • #nullable enable warnings: Setzt das Warnungsflag im nullfähigen Kontext auf aktiviert.
  • #nullable restore warnings: Stellt da Warnungsflag im nullfähigen Kontext auf die Projekteinstellungen wieder her.

Bedingte Kompilierung

Verwenden Sie vier Präprozessordirektiven, um die bedingte Kompilierung zu steuern:

  • #if: Startet eine bedingte Kompilierung. Der Compiler kompiliert den Code nur, wenn das angegebene Symbol definiert ist.
  • #elif: Schließt die vorangehende bedingte Kompilierung und öffnet eine neue bedingte Kompilierung, wenn das angegebene Symbol definiert ist.
  • #else: Schließt die vorangehende bedingte Kompilierung und öffnet eine neue bedingte Kompilierung, wenn das angegebene Symbol nicht definiert ist.
  • #endif: Schließt die vorangehende bedingte Kompilierung.

Das Buildsystem kennt zudem vordefinierte Präprozessorsymbole, die verschiedene Zielframeworks in Projekten im SDK-Format darstellen. Diese sind hilfreich, wenn Sie Anwendungen erstellen, die für mehr als eine .NET-Version bestimmt sind.

Zielframeworks Sonderzeichen 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, NET462_OR_GREATERNET461_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, , NETSTANDARD2_0NETSTANDARD1_6, 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, NET6_0_OR_GREATERNET5_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] (Beispiel: IOS15_1),
[OS][version]_OR_GREATER (Beispiel: 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.

Hinweis

Für herkömmliche Projekte, die kein SDK-Format aufweisen, müssen Sie die Symbole für die bedingte Kompilierung für die verschiedenen Zielframeworks in Visual Studio über die Eigenschaftenseite des Projekts manuell konfigurieren.

Andere vordefinierte Symbole beinhalten die Konstanten DEBUG und TRACE. Verwenden Sie diese Option #define , um die für das Projekt festgelegten Werte außer Kraft zu setzen. Das DEBUG Symbol wird z. B. automatisch abhängig von den Buildkonfigurationseigenschaften ("Debug" oder "Release"-Modus) festgelegt.

Der C#-Compiler kompiliert den Code zwischen der #if-Anweisung und der #endif-Anweisung nur, wenn das angegebene Symbol definiert bzw. bei Verwendung des Nicht-Operators ! nicht definiert ist. Im Gegensatz zu C und C++ können Sie einem Symbol keinen numerischen Wert zuweisen. Die #if-Anweisung in C# ist eine boolesche und testet nur, ob das Symbol definiert ist oder nicht. Beispielsweise wird der folgende Code kompiliert, wenn DEBUG definiert ist:

#if DEBUG
    Console.WriteLine("Debug version");
#endif

Der folgende Code wird kompiliert, wenn MYTESTnicht definiert ist:

#if !MYTEST
    Console.WriteLine("MYTEST is not defined");
#endif

Verwenden Sie die Operatoren == (Gleichheit) und != (Ungleichheit), um die bool Werte true oder false. true bedeutet, dass das Symbol definiert wurde. Die #if DEBUG-Anweisung hat die gleiche Bedeutung wie #if (DEBUG == true). Verwenden Sie die && Operatoren (and) und (oder) und (nicht), um auszuwerten,|| ob mehrere Symbole definiert sind.! Symbole und Operatoren können auch mit Klammern gruppiert werden.

Das folgende Beispiel zeigt eine komplexe Direktive, mit der Ihr Code neuere .NET-Features nutzen kann, während sie abwärtskompatibel bleiben. Angenommen, Sie verwenden ein NuGet-Paket in Ihrem Code, aber das Paket unterstützt nur .NET 6 und aufwärts, sowie .NET Standard 2.0 und aufwärts:

#if (NET6_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER)
    Console.WriteLine("Using .NET 6+ or .NET Standard 2+ code.");
#else
    Console.WriteLine("Using older code that doesn't support the above .NET versions.");
#endif

Wenn Sie #if mit den Direktiven #else, #elif, #endif, #define und #undef verwenden, können Sie Code je nach dem Vorhandensein eines oder mehrerer Symbole ein- oder ausschließen. Die bedingte Kompilierung kann hilfreich sein, wenn Code für einen Debugbuild oder für eine bestimmte Konfiguration kompiliert wird.

Mit #elif können zusammengesetzte bedingte Direktiven erstellt werden. Der Compiler wertet den #elif Ausdruck aus, wenn weder der vorhergehende noch der vorhergehende #if , optionale Direktivenausdrücke #elif ausgewertet truewerden. Wird ein #elif-Ausdruck als true ausgewertet, wird der gesamte Code zwischen der #elif-Anweisung und der nächsten bedingten Anweisung vom Compiler ausgewertet. Zum Beispiel:

#define VC7
//...
#if DEBUG
    Console.WriteLine("Debug build");
#elif VC7
    Console.WriteLine("Visual Studio 7");
#endif

Mit #else können zusammengesetzte bedingte Direktiven erstellt werden. Wenn keine der Ausdrücke in den vorherigen #if oder (optionalen) #elif Direktiven ausgewertet wird true, wertet der Compiler den gesamten Code zwischen #else und dem nächsten #endifaus. #endif muss die nächste Präprozessordirektive nach #elsesein.

#endif gibt das Ende einer bedingten Anweisung an, die mit der #if-Anweisung beginnt.

Das folgende Beispiel zeigt, wie Sie ein MYTEST Symbol in einer Datei definieren und dann die Werte der MYTEST Und-Symbole DEBUG testen. Die Ausgabe dieses Beispiels hängt davon ab, ob Sie das Projekt im Debug - oder Release-Konfigurationsmodus erstellt haben.

#define MYTEST
using System;
public class MyClass
{
    static void Main()
    {
#if (DEBUG && !MYTEST)
        Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && MYTEST)
        Console.WriteLine("MYTEST is defined");
#elif (DEBUG && MYTEST)
        Console.WriteLine("DEBUG and MYTEST are defined");
#else
        Console.WriteLine("DEBUG and MYTEST are not defined");
#endif
    }
}

Das folgende Beispiel zeigt, wie Sie nach verschiedenen Zielframeworks testen, damit Sie nach Möglichkeit neuere APIs verwenden können:

public class MyClass
{
    static void Main()
    {
#if NET40
        WebClient _client = new WebClient();
#else
        HttpClient _client = new HttpClient();
#endif
    }
    //...
}

Definieren von Symbolen

Verwenden Sie die folgenden beiden Präprozessordirektiven, um Symbole für die bedingte Kompilierung zu definieren oder rückgängig zu machen:

  • #define: Definiert ein Symbol.
  • #undef: Hebt die Definition eines Symbols auf.

Dient #define zum Definieren eines Symbols. Wenn Sie das Symbol als Ausdruck verwenden, der an die #if-Anweisung übergeben wird, wird der Ausdruck als true ausgewertet, wie in folgendem Beispiel dargestellt:

#define VERBOSE

#if VERBOSE
   Console.WriteLine("Verbose output version");
#endif

Hinweis

In C# sollten primitive Konstanten mithilfe des const Schlüsselworts definiert werden. Eine const-Deklaration erstellt ein static-Member, das zur Laufzeit nicht geändert werden kann. Die #define-Direktive kann nicht zur Deklaration konstanter Werte wie in C und C++ verwendet werden. Wenn Sie über mehrere solcher Konstanten verfügen, erwägen Sie, eine separate "Constants"-Klasse zu erstellen.

Verwenden Sie Symbole, um Bedingungen für die Kompilierung anzugeben. Testen Sie das Symbol mithilfe von #if oder #elif. Für die bedingte Kompilierung kann auch ConditionalAttribute verwendet werden. Ein Symbol kann zwar definiert werden, aber es kann ihm kein Wert zugewiesen werden. Die #define-Direktive muss in einer Datei vor allen Anweisungen, bei denen es sich nicht um Präprozessordirektiven handelt, verwendet werden. Sie können ein Symbol auch mithilfe der Compileroption DefineConstants definieren. Rückgängigmachen eines Symbols mithilfe von #undef.

Definieren von Bereichen

Definieren Sie Codebereiche, die Sie in einer Gliederung reduzieren können, indem Sie die folgenden beiden Präprozessordirektiven verwenden:

  • #region: Beginnt einen Bereich.
  • #endregion: Beendet einen Bereich.

Mit #region können Sie einen Codeblock festlegen, der bei Verwendung der Gliederungsfunktion des Code-Editors erweitert oder reduziert werden kann. Es ist bei längeren Codedateien praktischer, einen oder mehrere Bereiche zu reduzieren oder auszublenden, sodass Sie sich auf den Teil der Datei konzentrieren können, an dem Sie gerade arbeiten. Das folgende Beispiel veranschaulicht, wie Sie einen Bereich definieren:

#region MyClass definition
public class MyClass
{
    static void Main()
    {
    }
}
#endregion

Ein #region-Block muss mit einer #endregion-Anweisung beendet werden. Ein #region-Block kann sich nicht mit einem #if-Block überschneiden. Allerdings kann ein #region-Block in einen #if-Block und ein #if-Block in einen #region-Block geschachtelt werden.

Fehler- und Warnungsinformationen

Sie können die folgenden Direktiven verwenden, um benutzerdefinierte Compilerfehler und Warnungen zu generieren und Informationen zur Steuerungszeile zu erhalten:

  • #error: Generiert einen Compilerfehler mit einer angegebenen Meldung.
  • #warning: Generiert eine Compilerwarnung mit einer angegebenen Meldung.
  • #line: Ändert die Zeilennummer, die mit Compilermeldungen gedruckt wird.

Wird #error verwendet, um einen benutzerdefinierten CS1029-Fehler von einem bestimmten Speicherort in Ihrem Code zu generieren. Zum Beispiel:

#error Deprecated code in this method.

Hinweis

Der Compiler behandelt #error version auf besondere Weise und meldet den Compilerfehler CS8304 mit einer Nachricht, die die verwendeten Compiler- und Sprachversionen enthält.

Wird verwendet #warning , um eine CS1030-Compilerwarnung der Ebene 1 von einem bestimmten Speicherort im Code zu generieren. Zum Beispiel:

#warning Deprecated code in this method.

Dient #line zum Ändern der Zeilennummerierung des Compilers und (optional) der Dateinamenausgabe für Fehler und Warnungen.

Das folgende Beispiel zeigt, wie Sie zwei Warnungen melden können, die Zeilennummern zugeordnet sind. Die #line 200 Direktive zwingt die Nummer der nächsten Zeile auf 200 (obwohl der Standardwert #6 ist), und bis zur nächsten #line Direktive wird der Dateiname als "Special" gemeldet. Die #line default Direktive gibt die Zeilennummerierung an die Standardnummerierung zurück, wodurch die zeilenumnummeriert durch die vorherige Direktive gezählt werden.

class MainClass
{
    static void Main()
    {
#line 200 "Special"
        int i;
        int j;
#line default
        char c;
        float f;
#line hidden // numbering not affected
        string s;
        double d;
    }
}

Bei der Kompilierung wird die folgende Ausgabe erzeugt:

Special(200,13): warning CS0168: The variable 'i' is declared but never used
Special(201,13): warning CS0168: The variable 'j' is declared but never used
MainClass.cs(9,14): warning CS0168: The variable 'c' is declared but never used
MainClass.cs(10,15): warning CS0168: The variable 'f' is declared but never used
MainClass.cs(12,16): warning CS0168: The variable 's' is declared but never used
MainClass.cs(13,16): warning CS0168: The variable 'd' is declared but never used

Die #line-Anweisung könnte in einem automatischen Zwischenschritt im Buildprozess verwendet werden. Wenn Sie beispielsweise Zeilen aus der ursprünglichen Quellcodedatei entfernen, aber dennoch möchten, dass der Compiler die Ausgabe basierend auf der ursprünglichen Zeilennummerierung in der Datei generiert, können Sie Zeilen entfernen und dann die ursprüngliche Zeilennummerierung mithilfe von #line.

Die #line hidden Direktive blendet die aufeinander folgenden Zeilen aus dem Debugger aus. Wenn der Entwickler den Code durchläuft, werden alle Zeilen zwischen einer #line hidden und der nächsten #line Direktive (vorausgesetzt, dass sie keine andere #line hidden Direktive ist) übersprungen. Diese Option kann auch dazu verwendet werden, ASP.NET die Möglichkeit zu geben, zwischen benutzerdefiniertem und computergeneriertem Code zu unterscheiden. Obwohl ASP.NET der primäre Verbraucher dieses Features ist, ist es wahrscheinlich, dass mehr Quellgeneratoren es nutzen.

Eine #line hidden-Anweisung hat keine Auswirkung auf Dateinamen oder Zeilennummern bei der Fehlerberichterstattung. Wenn der Compiler einen Fehler in einem ausgeblendeten Block findet, meldet der Compiler den aktuellen Dateinamen und die Zeilennummer des Fehlers.

Die #line filename-Anweisung gibt den Dateinamen an, von dem Sie möchten, dass er in der Compilerausgabe erscheint. Standardmäßig wird der tatsächliche Name der Quellcodedatei verwendet. Der Dateiname muss sich in doppelten Anführungszeichen ("") befinden und einer Zeilennummer folgen.

Sie können eine neue Form der Direktive #line verwenden:

#line (1, 1) - (5, 60) 10 "partial-class.cs"
/*34567*/int b = 0;

Die Komponenten dieser Variante werden im Folgenden erläutert:

  • (1, 1): Dies ist die Startzeile und -spalte für das erste Zeichen in der Zeile, die auf die Anweisung folgt. In diesem Beispiel wird die nächste Zeile als Zeile 1, Spalte 1 gemeldet.
  • (5, 60): Dies ist die Endzeile und -spalte für den markierten Bereich.
  • 10: Dies ist der Spaltenversatz, der benötigt wird, damit die #line-Anweisung wirksam wird. In diesem Beispiel wird die 10. Spalte als Spalte 1 gemeldet. Die Deklaration int b = 0; beginnt an dieser Spalte. Dieses Feld ist optional. Wenn es nicht angegeben wird, wird die Anweisung in der ersten Spalte wirksam.
  • "partial-class.cs": Dies ist der Name der Ausgabedatei.

Im vorherigen Beispiel wird die folgende Warnung generiert:

partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its value is never used

Nach dem Neumapping befindet sich die Variable b in der ersten Zeile in Zeichen 6 der Datei partial-class.cs.

Domänenspezifische Sprachen (DSLs) verwenden dieses Format in der Regel, um eine bessere Zuordnung von der Quelldatei zur generierten C#-Ausgabe zu ermöglichen. Die häufigste Verwendung dieser erweiterten #line Direktive besteht darin, Warnungen oder Fehler, die in einer generierten Datei angezeigt werden, der ursprünglichen Quelle neu zuzuordnen. Betrachten Sie beispielsweise diese Razor-Seite:

@page "/"
Time: @DateTime.NowAndThen

Die Eigenschaft DateTime.Now wird falsch als DateTime.NowAndThen. Der generierte C#-Code für diesen Razor-Codeschnipsel sieht in page.g.cs wie folgt aus:

  _builder.Add("Time: ");
#line (2, 6) - (2, 27) 15 "page.razor"
  _builder.Add(DateTime.NowAndThen);

Die Compilerausgabe für den vorherigen Codeschnipsel lautet:

page.razor(2, 2, 2, 27)error CS0117: 'DateTime' does not contain a definition for 'NowAndThen'

Zeile 2, Spalte 6 in page.razor ist der Ort, an dem der Text @DateTime.NowAndThen beginnt, der von (2, 6) in der Richtlinie angegeben wird. Diese Spanne von @DateTime.NowAndThen endet bei Zeile 2, Spalte 27, wie in der Direktive durch (2, 27) angegeben. Der Text für DateTime.NowAndThen beginnt in Spalte 15 von page.g.cs, vermerkt durch die 15 in der Richtlinie. Der Compiler meldet den Fehler an der entsprechenden Stelle in page.razor. Der Entwickler kann direkt zum Fehler im Quellcode navigieren, anstatt in der generierten Quelle.

Weitere Beispiele für dieses Format finden Sie im Abschnitt Featurespezifikation zu den Beispielen.

Pragmas

Der Compiler verwendet #pragma spezielle Anweisungen zum Kompilieren der Datei, in der sie angezeigt wird. Der Compiler muss die verwendeten Pragmen unterstützen. Das heißt, Sie können mit #pragma keine benutzerdefinierten Präprozessoranweisungen erstellen.

#pragma pragma-name pragma-arguments

pragma-name ist der Name eines erkannten Pragmas. pragma-arguments ist die pragmaspezifischen Argumente.

#pragma Warnung

#pragma warning kann bestimmte Warnungen aktivieren oder deaktivieren. Die #pragma warning disable format und #pragma warning enable format steuern, wie Codeblöcke von Visual Studio formatiert werden.

#pragma warning disable warning-list
#pragma warning restore warning-list

warning-list ist eine durch Trennzeichen getrennte Liste von Warnnummern, z 414, CS3021. B. . Das Präfix „CS“ ist optional. Wenn Sie keine Warnungsnummern angeben, disable werden alle Warnungen deaktiviert und restore alle Warnungen aktiviert.

Hinweis

Um Warnzahlen in Visual Studio zu suchen, erstellen Sie Ihr Projekt und suchen Sie nach den Warnzahlen im Fenster Ausgabe.

disable wirkt sich ab der nächsten Zeile der Quelldatei aus. Die Warnung wird in der Zeile nach restore wiederhergestellt. Wenn keine Datei vorhanden ist restore , stellen die Warnungen in der ersten Zeile späterer Dateien in derselben Kompilierung wieder in ihren Standardzustand zurück.

// pragma_warning.cs
using System;

#pragma warning disable 414, CS3021
[CLSCompliant(false)]
public class C
{
    int i = 1;
    static void Main()
    {
    }
}
#pragma warning restore CS3021
[CLSCompliant(false)]  // CS3021
public class D
{
    int i = 1;
    public static void F()
    {
    }
}

Eine andere Form des warning pragma deaktiviert oder stellt Visual Studio-Formatierungsbefehle in Codeblöcken wieder her:

#pragma warning disable format
#pragma warning restore format

Visual Studio-Formatbefehle ändern keinen Text in Codeblöcken, in denen disable format wirksam ist. Formatbefehle, z. B. STRG+K, STRG+D-, ändern diese Codebereiche nicht. Mit diesem Pragma können Sie die visuelle Darstellung Ihres Codes genau steuern.

#pragma-Prüfsumme

Generiert Prüfsummen für Quelldateien, die beim Debuggen ASP.NET Seiten helfen.

#pragma checksum "filename" "{guid}" "checksum bytes"

Die Direktive verwendet "filename" den Namen der Datei, um Änderungen oder Aktualisierungen zu überwachen, als GUID (Globally Unique Identifier) für den Hashalgorithmus und "checksum_bytes" als Zeichenfolge von Hexadezimalziffern, "{guid}" die die Bytes der Prüfsumme darstellen. Sie müssen eine gerade Anzahl von Hexadezimalziffern angeben. Eine ungerade Anzahl von Ziffern führt zu einer Warnung zur Kompilierzeit, und die Anweisung wird ignoriert.

Der Visual Studio-Debugger verwendet eine Prüfsumme, um sicherzustellen, dass immer die richtige Quelle gefunden wird. Der Compiler berechnet die Prüfsumme für eine Quelldatei, und speichert das Ergebnis in der Program Database-Datei (PDB). Der Debugger verwendet den PDB zum Vergleichen mit der Prüfsumme, die für die Quelldatei berechnet wird.

Diese Lösung funktioniert nicht bei ASP.NET-Projekten, weil die berechnete Prüfsumme für die generierte Quelldatei und nicht für die ASPX-Datei gilt. #pragma checksum stellt für ASP.NET-Seiten Unterstützung von Prüfsummen bereit, um dieses Problem zu beheben.

Wenn Sie ein ASP.NET-Projekt in Visual C# erstellen, enthält die generierte Quelldatei eine Prüfsumme für die ASPX-Datei, von der die Quelle generiert wird. Der Compiler schreibt anschließend diese Informationen in die PDB-Datei.

Findet der Compiler keine #pragma checksum-Anweisung in der Datei, berechnet er die Prüfsumme und schreibt den Wert in die PDB-Datei.

class TestClass
{
    static int Main()
    {
        #pragma checksum "file.cs" "{406EA660-64CF-4C82-B6F0-42D48172A799}" "ab007f1d23d9" // New checksum
    }
}