小提示
剛開始開發軟體嗎? 你不會馬上需要預處理器指令。 先專注於 入門 教學,等到專案需要條件編譯或建置設定時再回來這裡。
有其他語言的經驗嗎? 如果你熟悉 #ifdef C/C++ 或其他語言的條件編譯,C# 預處理器指令的運作方式類似。 快速略過到你需要的語法。
C# 預處理器指令告訴編譯器在建置應用程式時該包含、排除或不同處理哪些程式碼。 此指引可能會改變最終的計畫。 預處理器指令總是以#開頭,必須出現在自己的行上(忽略前置空白)。 你可以在指令後加上尾記。 雖然 語言參考 書記錄了所有可用的指令,但有三類涵蓋日常使用:
-
檔案式應用程式 (
#:)- 設定檔案式應用程式。 -
條件編譯(
#if/#elif/#else/#endif)— 根據建置配置或目標框架,包含或排除程式碼。 -
警告抑制 (
#pragma warning)— 抑制或還原特定的編譯器警告。
基於檔案的應用程式指令
從 C# 14 開始, 基於檔案的應用程式 會使用兩個額外的指令:
-
#!— 那一行能直接在 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_GREATER 和NET8_0_OR_GREATER)允許你撰寫能適應不同 .NET 版本的多目標專案程式碼。
你可以將符號與邏輯運算子結合: && (和)、 || (或)、 ! (非):
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,而非關閉所有警告。 這種做法能讓壓制持續有針對性,並清楚說明 為什麼 要壓制警告。