プリプロセッサ ディレクティブ

ヒント

ソフトウェアの開発は初めてですか? プリプロセッサ ディレクティブはすぐには必要ありません。 プロジェクトで条件付きコンパイルやビルド構成が必要になった場合は、まずは「開始」のチュートリアルを見てからここに戻ってください。

別の言語で経験がありますか? C/C++ での #ifdef や他の言語での条件付きコンパイルに慣れている場合は、C# プリプロセッサ ディレクティブも同様に機能します。 必要な構文に進んでください。

C# プリプロセッサ ディレクティブは、アプリのビルド時に、どのコードを含めるか、除外するか、異なる方法で処理するかをコンパイラに指示します。 このガイダンスでは、結果のプログラムを変更できます。 プリプロセッサ ディレクティブは常に # で始まり、(先頭の空白文字を無視して) 独自の行に記述する必要があります。 ディレクティブの後に末尾のコメントを追加できます。 言語リファレンスには使用可能なすべてのディレクティブが記載されていますが、3 つのグループで日常的な使用について説明します。

  • ファイル ベースのアプリ (#:) - ファイルベースのアプリを構成します。
  • 条件付きコンパイル (#if / #elif / #else / #endif) - ビルド構成またはターゲット フレームワークに基づいてコードを含めるか除外します。
  • 警告の抑制 (#pragma warning) — 特定のコンパイラ警告を抑制または復元します。

ファイル ベースのアプリ ディレクティブ

C# 14 以降では、 ファイル ベースのアプリ では 2 つの追加ディレクティブが使用されます。

  • #! — Unix 上で直接ファイルを実行できるようにする shebang 行 (たとえば、 ./Program.cs)。 これには、ファイルに実行権限を設定する必要があります (chmod +x <file>)。
  • #: — 単一ファイル プログラムのパッケージ、SDK 設定、およびその他のオプションを構成するビルド システム ディレクティブ。

#:packageを使用して NuGet パッケージを追加します。 たとえば、次のファイル ベースのアプリでは、 Spectre.Console パッケージを使用してスタイル設定された出力をレンダリングします。

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

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

@で正確なバージョンを指定することも、@*を使用して最新バージョンをプルすることもできます。 複数の #:package ディレクティブを追加して、さらにパッケージを含めます。

#:package Serilog@3.1.1

他の #: ディレクティブを使用すると、プロジェクトの参照、MSBuild プロパティの設定、SDK の変更を行うことができます。

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

ディレクティブの完全な一覧については、 ファイルベースのアプリ言語リファレンスを参照してください

条件付きコンパイル

シンボルが定義されているかどうかに基づいてコードを含めたり除外したりするには、 #if#elif#else、および #endif を使用します。 最も一般的なシンボルは、 DEBUG (デバッグ ビルド用に自動的に設定) と、 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
}

ビルド システムは、デバッグ構成でビルドするときに DEBUG シンボルを定義します。 自分で定義する必要はありません。 NET10_0_OR_GREATERNET8_0_OR_GREATERなどのターゲット フレームワーク シンボルを使用すると、マルチターゲット プロジェクトのさまざまな .NET バージョンに適応するコードを記述できます。

&& (and)、|| (または)、! (not) の論理演算子とシンボルを組み合わせることができます。

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
}

ファイルの先頭にある #define を使用して、独自のシンボルを定義します。 プロジェクト ファイルの DefineConstants プロパティを使用して、プロジェクト全体のシンボルを定義することもできます。

警告の抑制

#pragma warning disableを使用して特定のコンパイラ警告を抑制し、再度有効にする#pragma warning restoreします。 常にできるだけ狭い範囲で抑制の範囲を指定します。

    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.");
        }
    }

ヒント

すべての警告を無効にするのではなく、常に警告番号 ( CS0168 など) を指定します。 この方法では、抑制の対象を維持し、警告が抑制されている 理由 を明確にします。