第 86 講:C# 2 之 #pragma warning 警告禁用指令
今天我們來看點不一樣的。
Part 1 早期禁用編譯器警告信息
還記得我們在學習語言配置的時候用到的 .csproj ?格式的文件嗎?這個文件專門對項目設(shè)置配置信息,比如 C# 的語言版本之類的。在這個文件里,我們還可以配置取消編譯器警告的信息。
我們先來回憶一下編譯器警告和編譯器錯誤。編譯器警告是一個提示信息,默認情況用的是綠色波浪線表示代碼段,表達這段代碼有一些運行期間無傷大雅,但不符合規(guī)范使用的信息。例如下面的代碼:

可以從代碼里看出,此時 hello
變量只定義了但沒有使用,因此編譯器會對這樣的錯誤使用給出編譯器警告。但是這樣的錯誤不是致命錯誤,因為它只是定義了沒使用,也不影響程序的正常執(zhí)行。
編譯器錯誤則是一個信息,表示代碼具有嚴重錯誤或無法編譯的致命錯誤信息。比如 C# 要求每一個語句要用分號結(jié)尾。但如果缺失分號,編譯器會自動產(chǎn)生編譯器錯誤信息。這樣的代碼是無法通過編譯的。
編譯器警告是不重要的錯誤,但多起來也挺煩人的。有些時候部分編譯器警告是可以忽略掉的,因此滿篇都是綠色的波浪線看著也挺不舒服的。因此我們可以對這些編譯器警告信息予以忽略操作。讓編譯器不再對這些錯誤產(chǎn)生警告。
辦法是這樣的:我們打開項目的 .csproj 為后綴名的配置文件,它一般都長這樣:
<PropertyGroup>
標簽里,在和 <TargetFramework>
標簽同級別的地方配上 <NoWarn>
標簽,里面寫 CS0219
這里 <NoWarn>
標簽表示的是,整個項目需要禁用掉哪些警告信息,下次編譯器就不會對這些信息報錯了。里面寫的是警告禁用的編號代碼。我們回到最開始那個圖片上,你可以看到,CS0219
后跟上了錯誤的信息內(nèi)容和解釋文字,而這個 CS0219
,就是編譯器對這些警告或錯誤信息給出的唯一編號。你只需要把對應(yīng)的錯誤編號寫到 <NoWarn>
里后,所有 CS0219
錯誤的信息,編譯器就不再會給出了。
回到代碼:

你會發(fā)現(xiàn),缺失警告的波浪線消失了。這個就是配置和取消警告信息的過程。
但是可以發(fā)現(xiàn),這樣的配置有一個嚴重的弊端:它是對整個項目起效的。它無法對文件為單位取消警告信息,整個項目都取消的話,這個范圍未免也有點太大了一些。所以,原生的 C# 并不支持文件為單位的警告信息取消。
另外,Visual Studio 定義了四種編譯器報錯的級別,分別是 Hidden(隱藏級別報錯)、Info(信息級別報錯)、Warning(警告級別報錯)和 Error(錯誤級別報錯)。而綠色波浪線的錯誤信息級別是 Warning 級別。而 Visual Studio 還定義了兩種級別,一個叫 Hidden,一個叫 Info。Hidden 級別的編譯器信息,不會用任何的標記來標記錯誤書寫的代碼段,唯一能發(fā)覺到它的存在的辦法是,把你的代碼光標(就是標識你書寫代碼到哪里的那個文字間的閃爍豎線條)放在這個所在行上,然后你會在代碼所在行的行號旁看到一個燈泡圖標,里面可以看到對應(yīng)的信息;而 Info 級別會有標記錯誤代碼段落的標記,不過它不是綠色也不是紅色波浪線,而是灰色的四個小圓點,標識你的錯誤代碼段開頭的位置上。這樣的標記很不容易引起注意,因為它比起編譯器警告信息來說還要低一個級別,這類警告信息,你改不改正都無傷大雅。而比 Info 大一個級別的才是編譯器警告(Warning 級別),最后才是編譯器錯誤(Error 級別)。
Part 2 #pragma warning disable
指令
C# 2 為了解決這樣的錯誤提示消除過程無法實現(xiàn)的問題,誕生了新的語句:#pragma warning disable
指令。
#pragma warning disable
指令是一個組合單詞的指令,也就是說,pragma
、warning
和 disable
這三個單詞都必須一起寫出來,而且必須是先 pragma
后 warning
,最后是 disable
;另外,在 pragma
前面,還需要加上預(yù)處理指令的井號 #
標記。
我們把它當成是一個預(yù)處理指令一樣的使用就行。不過這個預(yù)處理指令和 #region
還有 #endregion
類似,它可以用于任何代碼行上。以前的 #if
只能放在文件開頭,或者前面帶有一些 using
指令什么的。但 #pragma warning disable
指令可以寫在任何位置。唯一需要注意的是,它是預(yù)處理指令,因此必須單獨占據(jù)一行;也就是說你不能對 #pragma warning disable
這三個單詞的每兩個單詞中間插入換行,這是唯一需要注意的。
比如,給出一個簡單的示例程序:
其中:
IDE0059
信息:對一個變量的賦值沒有意義;CS0219
信息:變量定義了但沒有使用過;IDE0005
信息:using
指令沒有使用過。
你可以使用這個語法來對它們的錯誤信息進行消除。當然,C# 也允許你寫在一行里:
用逗號分隔每一個編號即可。
Part 3 #pragma warning restore
指令
當然,#pragma warning
也不是必須跟 disable
。C# 2 為了更為靈活地控制編譯器警告報錯的過程,該指令還有一個寫法:#pragma warning restore
。它表示,既報錯禁用后,恢復對指定編號的報錯。
#pragma warning restore
的語法和 #pragma warning disable
的語法完全一樣,即后面跟上的是錯誤編號(如果是多個錯誤編號的話,用逗號分開),但 #pragma warning restore
一般用在它的前面已經(jīng)出現(xiàn)過 #pragma warning disable
的同編號錯誤警告的時候。舉個例子,我現(xiàn)在有這樣的代碼:

它表示計算一個數(shù)字的階乘。但是這個方法我們尚未使用過,因此我們會在方法的上方插入一個 #pragma warning disable
的警告禁用指令。不過,我如果在 Factorial
方法下面還有別的代碼的話,這個警告禁用的范圍就超出了我們預(yù)想的范圍:我們只想要禁用掉 Factorial
這一個方法的使用性的報錯,而別的方法不影響。
我們可以這么寫:
我們可在報錯的 Factorial
方法簽名所在行的上下方各插入一行指令。上面是報錯,下面是 restore
恢復報錯。這里的 IDE0051
就是表示“方法沒有使用過”的報錯信息。
有人會問,為什么 restore
這個指令寫在第 3 行而不是第 10 行后?因為編譯器分析和報錯只位于整個方法的簽名上(你可以看到前面給出的圖片,四個小圓點只出現(xiàn)在 Factorial
這個方法名上,而不是整個方法都標上了灰色的四個小圓點。所以,我們只需要插入到這里即可。當然了,你寫在第 10 行后也是可以的,也沒有錯誤就是了。
Part 4 #warning
的禁用
C# 早期還有一個叫做 #warning
的指令,它用來控制和表示在當前位置直接產(chǎn)生編譯器警告信息。
比如這樣的代碼,我們可以看到第 14 行有一個 #warning
指令。我們此時可以直接在第 14 行獲得一個編譯器警告信息。不過,如果你要禁用這段代碼的錯誤,這里就需要了解一下,#warning
指令的報錯機制了。
#warning
占用了編譯器警告編號是 CS1030
。也就是說,你寫的 #warning
默認都會產(chǎn)生編號為 CS1030
的編譯器警告信息。如果你要想禁用掉,使用 #pragma warning disable CS1030
即可。
比如這樣。當然了,畢竟是我們自己臨時自定義的警告信息,我們也不建議對自己添加的警告信息再次取消掉它的報錯。
Part 5 簡記 CS 系列錯誤編號
Visual Studio 發(fā)展到現(xiàn)在,擁有眾多的編譯器分析出來的編號代碼。其中常見的有這些:
CS 系列:C# 語言自身派生的基本語法分析的錯誤和警告信息;
IDE 系列:和 Visual Studio 綁定的、和你書寫的代碼可以產(chǎn)生交互的編譯器警告信息;
CA 系列:官方提供的、補充的編譯器錯誤和警告信息。
當然還有一些別的,什么 RS 開頭的啊,SA 開頭的,DA 開頭等等的系列。不過這里我們要說的是 CS 開頭的。CS 是 C# 語法分析的結(jié)果導致的唯一編號序列,它們在使用 #pragma warning
指令的時候,可以不寫 CS 前綴,比如 CS1030
可以直接記作 1030
,等等。
比如最開始的禁用的代碼:
這個 CS0219
可以直接記作 0219
或 219
。但別的,都必須帶上開頭的字母。
Part 6 不能禁用掉編譯器錯誤
編譯器錯誤一般而言是無法禁用的,原因很簡單:比如你寫的忘了分號的語法錯誤,編譯器肯定是不讓編譯通過的。因此,#pragma warning
肯定無法使用到這種場合上。它屬于嚴重的錯誤,不屬于去掉編譯器警告就能消除掉的錯誤類型。