Directives de préprocesseur

Conseil / Astuce

Vous débutez avec le développement de logiciels ? Vous n’aurez pas besoin de directives de préprocesseur immédiatement. Concentrez-vous d’abord sur les didacticiels de prise en main et revenez ici lorsque vos projets nécessitent une compilation conditionnelle ou une configuration de build.

Maîtrisez-vous une autre langue ? Si vous êtes familiarisé avec #ifdef C/C++ ou la compilation conditionnelle dans d’autres langages, les directives de préprocesseur C# fonctionnent de la même façon. Parcourez la syntaxe dont vous avez besoin.

Les directives de préprocesseur C# indiquent au compilateur le code à inclure, exclure ou traiter différemment quand il génère votre application. Ces conseils peuvent modifier le programme résultant. Les directives de préprocesseur commencent toujours par # et doivent apparaître sur leur propre ligne (en ignorant les espaces blancs en début de ligne). Vous pouvez ajouter un commentaire de fin après la directive. Bien que la référence linguistique documente toutes les directives disponibles, trois groupes couvrent l’utilisation quotidienne :

  • Applications basées sur des fichiers (#:) : configurez des applications basées sur des fichiers.
  • Compilation conditionnelle (#if / #elif / #else / #endif) : incluez ou excluez du code en fonction de la configuration de build ou de l’infrastructure cible.
  • Suppression d’avertissement (#pragma warning) : supprimez ou restaurez des avertissements spécifiques du compilateur.

Directives d’application basées sur des fichiers

À compter de C# 14, les applications basées sur des fichiers utilisent deux directives supplémentaires :

  • #!— ligne shebang qui permet d’exécuter le fichier directement sur Unix (par exemple). ./Program.cs Cela nécessite que l’autorisation d’exécution soit définie sur le fichier (chmod +x <file>).
  • #: — directives de système de build qui configurent des packages, des paramètres du KIT de développement logiciel (SDK) et d’autres options pour les programmes à fichier unique.

Permet #:package d’ajouter un package NuGet. Par exemple, l'application fondée sur des fichiers suivante utilise le paquet Spectre.Console pour afficher une sortie stylisée :

#!/usr/bin/env dotnet
#:package Spectre.Console@*

AnsiConsole.MarkupLine("[bold green]Hello[/] from a file-based app!");

Vous pouvez spécifier une version exacte avec @, ou l’utiliser @* pour extraire la dernière version. Ajoutez plusieurs #:package directives pour inclure d’autres packages :

#:package Serilog@3.1.1

D’autres #: directives vous permettent de référencer des projets, de définir des propriétés MSBuild ou de modifier le Kit de développement logiciel (SDK) :

#:project ../SharedLibrary/SharedLibrary.csproj
#:property PublishAot=false
#:sdk Microsoft.NET.Sdk.Web

Pour obtenir la liste complète des directives, consultez les applications basées sur des fichiers et la référence du langage.

Compilation conditionnelle

Utilisez #if, #elif, #elseet #endif pour inclure ou exclure du code selon qu’un symbole est défini. Les symboles les plus courants sont DEBUG (définis automatiquement pour les builds de débogage) et les symboles de framework cible comme NET10_0_OR_GREATER:

static void ConfigureLogging()
{
#if DEBUG
    Console.WriteLine("Debug logging enabled — verbose output active.");
#else
    Console.WriteLine("Release logging — errors only.");
#endif
}

Le système de compilation définit le symbole DEBUG lorsque vous compilez dans la configuration de débogage. Vous n’avez pas besoin de le définir vous-même. Les symboles de framework cible comme NET10_0_OR_GREATER et NET8_0_OR_GREATER vous permettent d’écrire du code qui s’adapte à différentes versions de .NET dans des projets multi-ciblage.

Vous pouvez combiner des symboles avec des opérateurs logiques : && (et), || (ou) et ! (pas) :

static void ShowPlatformInfo()
{
#if NET10_0_OR_GREATER
    Console.WriteLine("Running on .NET 10 or later.");
#elif NET8_0_OR_GREATER
    Console.WriteLine("Running on .NET 8 or 9.");
#else
    Console.WriteLine("Running on an older .NET version.");
#endif
}

Utilisez #define en haut d’un fichier pour définir vos propres symboles. Vous pouvez également définir des symboles pour l’ensemble du projet à l’aide de la DefineConstants propriété dans votre fichier projet.

Suppression d’avertissement

Permet #pragma warning disable de supprimer des avertissements de compilateur spécifiques et #pragma warning restore de les réactiver. Limitez toujours la suppression aussi étroitement que possible :

    static void ProcessData()
    {
        try
        {
            // Some operation that might fail
            var data = File.ReadAllText("config.json");
            Console.WriteLine($"Config loaded: {data.Length} characters");
        }
#pragma warning disable CS0168 // Variable is declared but never used
        catch (FileNotFoundException ex)
#pragma warning restore CS0168
        {
            // Fall back to defaults — the exception details aren't needed here
            Console.WriteLine("Config file not found, using defaults.");
        }
    }

Conseil / Astuce

Spécifiez toujours le numéro d’avertissement, comme CS0168, plutôt que de désactiver tous les avertissements. Cette approche maintient la suppression ciblée et indique clairement pourquoi un avertissement est supprimé.