C# 預處理指令雖不影響 IL 產出,卻能控制編譯器行號報告、警告抑制、偵錯體驗、原始碼產生器整合等關鍵行為。本文深入解析 #line 與 #pragma warning 兩大實用指令。
#line:重寫編譯器行號與檔案名#line number ["filename"]
#line default
#line hidden
class Demo
{
static void Main()
{
#line 200 "CustomFile.cs"
int i; // CS0168 將回報:CustomFile.cs(200,9)
#line default
char c; // CS0168 回報:實際檔案第 9 行
}
}
| 場景 | 指令組合 | 效果 |
|---|---|---|
| 原始碼產生器 | #line 42 "Original.template" | 錯誤/警告指向原始模板而非產出檔,便於修正模板 |
| 隱藏樣板碼 | #line hidden ... #line default | 偵錯時 F11 跳過隱藏區塊,斷點不會停在內部 |
| ASP.NET Razor | 框架自動插入 | 區分使用者程式碼與框架生成程式碼,堆疊追蹤更清晰 |
| 自動化重構工具 | 移除行後保持原行號 | 版本控制 diff 僅顯示實質變更,編譯器輸出與原始碼同步 |
#line hidden 不影響 錯誤行號回報,僅影響偵錯器逐步執行行為。#line default 恢復預設行號計算(含前面所有隱藏行)。#pragma warning:精準控制警告輸出
#pragma warning disable 警告清單 // 關閉指定警告
#pragma warning restore 警告清單 // 恢復預設行為
#pragma warning disable // 關閉所有警告(不建議)
#pragma warning restore // 恢復所有警告
警告編號不含 CS 前綴,如 0168、0618、0414。
// 關閉:未使用變數(0168)、過時成員(0618)、欄位未讀取(0414)
#pragma warning disable 0168, 0618, 0414
public class LegacyInterop
{
int unusedField = 10; // 0168 不會顯示
[Obsolete("請用 NewMethod")] // 0618 不會顯示
public void OldMethod() { }
public void Caller()
{
int temp = 5; // 0168 不會顯示
OldMethod(); // 0618 不會顯示
}
}
#pragma warning restore 0168, 0618, 0414 // 恢復專案級設定
| 層級 | 設定方式 | 影響範圍 | 優先序 |
|---|---|---|---|
| 專案級 | .csproj <NoWarn> / VS 屬性頁「建置」→「隱藏警告」 | 整個專案 | 基準 |
| 檔案級 | 檔案最上方 #pragma warning disable 0168 | 單一檔案 | 覆蓋專案級 |
| 區塊級 | #pragma warning disable/restore 包圍 | 指定程式碼區塊 | 最高(最精準) |
| 編號 | 完整代碼 | 含義 | 典型抑制場景 |
|---|---|---|---|
| 0168 | CS0168 | 變數已宣告但未使用 | Interop 介面預留參數、暫時註解邏輯 |
| 0618 | CS0618 | 過時成員 | 漸進式遷移期間呼叫舊 API |
| 0414 | CS0414 | 私有欄位已指派但未讀取 | 序列化/反射/原生互操作需求 |
| 0649 | CS0649 | 欄位未被指派(永遠為預設值) | Unity `[SerializeField]`、DI 容器注入 |
| 0169 | CS0169 | 私有欄位從未使用 | 同上 |
#if DEBUG
#pragma warning disable 0162 // 無法到達的程式碼(DEBUG 區塊常見)
#endif
// 僅 DEBUG 執行的驗證邏輯
#if DEBUG
#pragma warning restore 0162
#endif
#line hidden 實測
using System;
class DebugDemo
{
static void Main()
{
Console.WriteLine("正常行 1"); // 斷點 1:會停
#line hidden
Console.WriteLine("隱藏行"); // 斷點 2:不會停,F11 直接跳過
#line default
Console.WriteLine("正常行 2"); // 斷點 3:會停
}
}
此特性常用於:原始碼產生器輸出的對應關係、AOP 編織碼、框架內部樣板碼。
// #pragma warning disable 0618 - 相容舊版 API,v2.0 移除。#pragma warning 使用情況,已遷移完成者移除抑制。#line 指令,大幅提升使用者體驗。