標籤:
在C#中有許多名為“預先處理指令”的命令,這些命令從來不會轉化為可執行代碼中的命令,但會影響編譯過程的各個方面。例如,使用前置處理器指令可以禁止編譯器編譯代碼的某一部分。如果計劃發布兩個版本的代碼,即基本版本和擁有更多功能的企業版本,就可以使用這些前置處理器指令。在編譯軟體的基本版本時,使用前置處理器指令可以禁止編譯器編譯與額外功能相關的代碼。另外,在編寫提供調試資訊的代碼時,也可以使用前置處理器指令。實際上,在銷售軟體時,一般不希望編譯這部分代碼。
預先處理指令的開頭都有符號#。
1. #define和#undef
#define的用法如下所示:
#define DEBUG
它告訴編譯器存在給定名稱的符號,在本例中是DEBUG。這有點類似於聲明一個變數,但這個變數並沒有真正的值,只是存在而已。這個符號不是實際代碼的一部分,而只在編譯器編譯代碼時存在。在C#代碼中它沒有任何意義。
#undef正好相反,它刪除符號的定義:
#undef DEBUG
如果符號不存在,#undef就沒有任何作用。同樣,如果符號已經存在,則#define也不起作用。必須把#define和#undef命令放在C#源檔案的開頭位置,在聲明要編譯的任何對象的代碼之前。#define本身沒有什麼用,但與其他前置處理器指令(特別是#if)結合使用時,它的功能就非常強大了。
2. #if/#elif/#elese/#endif
這個指令告訴編譯器是否要編譯某個代碼塊。考慮下面的方法:
int DoSomeWork(double x){ //do something #if DEBUG Console.WriteLine("x is "+x); #endif}
這段代碼會像往常一樣編譯,但是Console.WriteLine命令包含在#if子句內。這行代碼只有在前面的#define命令定義了符號DEBUG後才執行。當編譯器遇到#if語句後,將先檢查相關的符號是否存在,如果符號存在,就編譯#if子句中的代碼。否則,編譯器會忽略所有的代碼,直到遇到匹配的#endif指令為止。一般是在調試時定義符號DEBUG,把與調試相關的代碼放在#if子句中。在完成了調試後,就把#define語句注釋掉,所有的調試代碼會奇蹟般消失,可執行檔也會變小,最終用會不會被這些調試資訊弄糊塗。這項技術在C和C++中十分常見,稱為條件編譯.
#elif(=else if)和#else指令可以用在#if塊中,其含義非常直觀。也可以嵌套#if塊:
#define ENTERPRISE#define W2K//further on in the file#if ENTERPRISE //so something #if W2K //some code that is only relevant to enterprise //edition running on W2K #endif#elif PROFESSIONAL //do something else #else //code for the leaner version #endif
#if和#elif還支援一組邏輯運算子"!"/"=="/"!="/"||"。如果符號存在,就被認為是true,否則為false,例如:
#if W2K && (ENTERPRISE==false) //if W2K is defined but ENTERPRISE isn‘t
範例 // preprocessor_if.cs #define DEBUG #define VC_V7 using System; public class MyClass { static void Main() { #if (DEBUG && !VC_V7) Console.WriteLine("DEBUG is defined"); #elif (!DEBUG && VC_V7) Console.WriteLine("VC_V7 is defined"); #elif (DEBUG && VC_V7) Console.WriteLine("DEBUG and VC_V7 are defined"); #else Console.WriteLine("DEBUG and VC_V7 are not defined"); #endif } }輸出DEBUG and VC_V7 are defined
3. #warning和#error
另兩個非常有用的前置處理器指令是#warning和#error,當編譯器遇到它們時,會分別產生警告或錯誤。如果編譯器遇到#warning指令,會給使用者顯示#warning指令後面的文本,之後編譯繼續進行。如果編譯器遇到#error指令,就會給使用者顯示後面的文本,作為一條編譯錯誤訊息,然後會立即退出編譯,不會產生IL代碼。
使用這兩條指令可以檢查#define語句是不是做錯了什麼事,使用#warning語句可以讓自己回顧 一下進行了哪些操作:
#if DUBUG && RELEASE #error "You‘ve defined DEBUG and RELEASE simultaneously!"#endif#warning "Don‘t forget to remove this line before the boss tests the code!" Console.WriteLine("*I hate this job*");
4. #line
#line指令可以用於改變編譯器在警告和錯誤資訊中顯示的檔案名稱和行號資訊。這條指令用得並不多。如果編寫代碼時,在把代碼發送給編譯器前,要使用某些軟體包改變輸入的代碼,就可以使用這個指令,因為這意味著編譯器報告的行號或檔案名稱與檔案中的行號或編輯的檔案名稱不匹配。#line指令可以用於還原這種匹配。也可以使用文法#line default把行號還原為預設的行號:
#1ine 164 "Core.cs" // we happen to know this is line 164 in the file // Core.cs, before the intermediate // package mangles it.// later on#line default // restores default line numbering
5. #pragma
#pragma指令可以抑制或者還原指定的編譯警告。與命令列選項不同,#pragma指令可以在類或方法層級執行,對抑制警告的內容和抑制的時間進行更精細的控制。下面的例子禁止"欄位未使用"警告,然後在編譯MyClass類後還原該警告。
#pragma warning disable 169Public class MyClass{ int neverUsedField; }#pragma warning restore 169
C#前置處理器指令