C# 無獨立前置處理器,指令作為詞法分析階段執行。所有指令以 # 開頭,必須獨佔一行 (前可有空白)。
#define DEBUG // 定義符號 (無值,只有有/無)
#define TRACE
#undef TRACE // 取消定義
// 符號作用域:整個原始檔
// 必須出現在「實際程式碼」之前 (using、namespace、class 等之前)
// 錯誤範例:
using System;
#define DEBUG // CS1024: 前置處理器指示詞必須在檔案最前面
#define DEBUG
#define VERBOSE
#if DEBUG && VERBOSE
Console.WriteLine("Debug + Verbose");
#elif DEBUG
Console.WriteLine("Debug only");
#elif RELEASE
Console.WriteLine("Release");
#else
Console.WriteLine("Other");
#endif
// 邏輯運算子:&& (且)、|| (或)、! (非)、== != (比較)
// 可巢狀
#if DEBUG
#if VERBOSE
LogDetail();
#endif
#endif
#if 開始 (必要)#elif#else#endif 結束 (必要)
#define DEMO_VERSION
#define DEBUG
#if DEMO_VERSION && !DEBUG
#warning 您正在建置 Demo 版本 (非 Debug)
#endif
#if DEBUG && DEMO_VERSION
#error 無法建置 Debug 版 Demo (邏輯衝突)
#endif
// 實際建置輸出:
// warning CS1030: 您正在建置 Demo 版本 (非 Debug)
// error CS1029: 無法建置 Debug 版 Demo (邏輯衝突)
用途:強制建置規則、提醒配置衝突、標記未完成功能。
#define TRACE
public class Logger
{
public static void Trace(string msg)
{
#if TRACE
Console.WriteLine($"[TRACE] {DateTime.Now}: {msg}");
#endif
}
}
#if NETFRAMEWORK
using System.Web;
#elif NETCOREAPP
using Microsoft.AspNetCore.Http;
#endif
public class ContextAccessor
{
#if NETFRAMEWORK
public static HttpContext Current => HttpContext.Current;
#elif NETCOREAPP
public static HttpContext Current => new HttpContextAccessor().HttpContext;
#endif
}
#define ENABLE_NEW_UI
public class UiManager
{
public void Render()
{
#if ENABLE_NEW_UI
RenderNewUi();
#else
RenderLegacyUi();
#endif
}
}
// 錯誤:前置處理器不處理字串字面值內容
Console.WriteLine(@"Hello #if DEBUG World #else Everyone #endif");
// 輸出原文:Hello #if DEBUG World #else Everyone #endif
// 正確:分開字串
#if DEBUG
Console.WriteLine("Hello World");
#else
Console.WriteLine("Hello Everyone");
#endif
using System.Diagnostics;
public class Diagnostics
{
[Conditional("DEBUG")]
public static void Assert(bool condition, string message)
{
if (!condition) throw new InvalidOperationException(message);
}
[Conditional("TRACE")]
public static void Log(string msg) => Console.WriteLine(msg);
}
// 呼叫端
Diagnostics.Assert(x > 0, "x must be positive"); // DEBUG 定義時保留,否則呼叫與評估參數皆移除
[Conditional] 比 #if 更優雅:連同參數評估一併移除,避免副作用。
條件編譯是建置時期的靜態決策工具。善用 #define/#if 隔離平台差異、控制功能開關、除錯追蹤;用 #error/#warning 強制團隊規範;優先考慮 [Conditional] 處理方法層級條件編譯,獲得更乾淨的語意與參數評估控制。