下面對C#中的預編譯指令進行介紹:html
用法:git
#define DEBUG編輯器
#undef DEBUGide
#define告訴編譯器,我定義了一個DEBUG的一個符號,他相似一個變量,可是它沒有具體的值,能夠將它看爲一個符號而已。#undef就是刪除這個符號的定義。若是符號DEBUG沒定義過,則#undef不起做用,不然#define不起做用。兩者都必須放在源代碼以前。兩者的順序看代碼的順序:佈局
#define DEBUG post
#undef DEBUGui
這樣的話,DEBUG是沒有定義的,若是兩者換個順序,編譯器就認爲DEBUG被定義了this
這個告訴編譯器進行編譯代碼的流程控制。考慮下面代碼:編碼
#if DEBUGspa
Console.Write("debug");
#elif RELEASE
Console.Write("release");
#else
Console.Write("other");
#endif
以上代碼就是說若是定義了DEBUG則輸出debug,定義了RELEASE,則輸出realse,不然輸出other。若是定義了DEBUG和REALSE會怎麼樣呢?各位能夠本身試一下。
經過這兩個指定能夠告訴編譯器,出一個警告仍是錯誤信息。除了錯誤信息之後,編譯將中止。
參考下面的代碼(C#在Debug狀態下自動定義DEBUG標誌,但Release狀態不會自動定義RELEASE標誌):
#if DEBUG
#warning 如今是Debug狀態
#elif RELEASE
#warning 如今是Release狀態
#else
#error 並清楚什麼狀態
#endif
這個兩個用來組成代碼塊。
這個指令能夠改變編譯器在警告和錯誤信息中顯示的文件名和行號信息,用#line default把行號恢復爲默認的行號。
#line [ number ["file_name"] | default ]
number
要爲源代碼文件中後面的行指定的編號。
"file_name"(可選)
但願出如今編譯器輸出中的文件名。默認狀況下,使用源代碼文件的實際名稱。文件名必須括在雙引號 ("") 中。
default
重置文件中的行編號。
備註:
#line 可能由生成過程當中的自動中間步驟使用。例如,若是中間步驟從原始的源代碼文件中移除行,可是您仍但願編譯器基於文件中的原始行號生成輸出,則能夠移除行,而後用 #line 模擬原始行號。
下面的示例說明如何報告與行號關聯的兩個警告。#line 200 指令迫使行號爲 200(儘管默認值爲 #7)。另外一行 (#9) 做爲默認 #line 指令 的結果跟在一般序列後。
示例1:
// preprocessor_line.cs
public class MyClass2
{
public static void Main()
{
#line 200
int i; // line 200
#line default
char c; // line 9
}
}
示例2:
下面的示例說明調試器如何忽略代碼中的隱藏行。運行此示例時,它將顯示三行文本。可是,當設置如示例所示的斷點並按 F10 鍵逐句經過代碼時,您將看到調試器忽略了隱藏行。另請注意,即便在隱藏行上設置斷點,調試器仍會忽略它。
// preprocessor_linehidden.cs
using System;
class MyClass
{
public static void Main()
{
Console.WriteLine("Normal line #1."); // Set a break point here.
#line hidden
Console.WriteLine("Hidden line.");
#line default
Console.WriteLine("Normal line #2.");
}
}
能夠抑制或恢復指定的編譯警告。與命令行選項不一樣,#pragma指令能夠在類和方法上執行,對抑制什麼警告和抑制的時間進行更精細的控制。
#pragma warning disable 169
public class Aclass
{
int nFiled;
}
#pragma warning restore 169
出處:http://blog.sina.com.cn/s/blog_6ae1dc950100nf3f.html
======================================================================================
C#的預處理器指令很容易識別,你看到了#,就能認出它們。
它和其餘的命令有什麼區別呢?
區別在於這些命令歷來不會轉化爲可執行代碼的命令,可是會影響編譯過程的各個方面。
它用來作什麼呢?
當計劃發佈兩個版本的代碼的時候。即基本版和擁有更多版本的企業版,就能夠用到預處理器指令。
在編譯基本版的時候,使用預處理指令會禁止編譯器編譯與額外功能相關的代碼。
另外,在編寫提供調試信息的代碼時,也可使用預處理器指令。
下面介紹預處理器指令的功能:
#define和#undef
#define用法: #define Debug
Debug能夠看作是聲明的一個變量,但此變量沒有真正的值,僅存在。
#define單獨用沒什麼意義,通常是和#if結合使用。
#undef用法: #undef Debug
做用就是刪除Debug的定義。若是Debug符號不存在,這條指令就沒有任何做用。若是Debug符號存在,則以前的#define就沒有做用。
#define與#undef聲明必須放在C#源文件的開頭位置,即程序集的引用的上方。
#if,#elif,#else和#endif
下面來看一個例子
//#define DebugA #define DebugB using System; namespace MyApplication { class Program { static void Main(string[] args) { #if DebugA Console.WriteLine("Hello DebugA"); #elif DebugB Console.WriteLine("Hello DebugB"); #else Console.WriteLine("Hello Debugelse"); #endif } } }
#elif(=else if)和#else指令能夠用在#if中,和C#中的if,else if,else含義相同。
#if和#elif支持一組邏輯運算符"!","==","!="和"||",若是符號存在,則爲true。
#if DebugB && DebugA //當Debug與DebugA同時存在纔會執行
#warning和#error
當編譯器遇到這兩條指令時,會分別產生警告和錯誤。若是編譯器遇到#warning指令,會顯示該指令後的文本,以後繼續編譯。
若是碰見#error指令,也會顯示指令後面的文本。但會馬上退出編譯,不會產生IL代碼。(其實和編譯器的警告和錯誤意義相同)
static void Main(string[] args) { #warning "All Right?" Console.WriteLine("Contine..."); //#error "All Right?" // Console.WriteLine("Contine..."); }
下圖爲放開#error註釋:
#region和#endregion
這兩條指令,你們應該很是熟悉,做用就是代碼縮進和指定該代碼塊的名稱,使得代碼能夠更好的佈局。詳細用法能夠參照報表系列的代碼。
#line
這條指令不多用到。做用就是:若是代碼在編譯以前,要使用某些軟件包改變輸入的代碼,就可使用它。
(其實就是更改代碼的行號)
#pragma warning
此指令可啓用或禁用某些警告。
用法: #pragma warning disable warning-list
#pragma warning restore warning-list
例子:
using System; #pragma warning disable 414, 3021 [CLSCompliant(false)] public class C { int i = 1; static void Main() { } } #pragma warning restore 3021 [CLSCompliant(false)] // CS3021 public class D { int i = 1; public static void F() { } }
#pragma checksum
做用是生成源文件的校驗和,以幫助調試 ASP.NET 頁。
用法: #pragma checksum "filename" "{guid}" "checksum bytes"
filename" 要求監視更改或更新的文件的名稱。
"{guid}" 文件的全局惟一標識符 (GUID)。
"checksum_bytes" 十六進制數的字符串,表示校驗和的字節。必須是偶數位的十六進制數。
奇數位的十六進制數字會致使編譯時警告,而後指令被忽略。
例子:
class TestClass { static int Main() { #pragma checksum "file.cs" "{3673e4ca-6098-4ec1-890f-8fceb2a794a2}" "{012345678AB}" // New checksum } }
出處:http://www.cnblogs.com/ck-winner/archive/2013/02/05/2892756.html
===================================================================================
重要說明:
預處理指令都以#號開頭並位於行首前面能夠出現空格符。
上面的語句定義了連個個預編譯的符號,他的做用域是他所處整個文件,定義符號的語句必須出如今全部代碼以前, 不然編譯的時候會出現一個異常: 不能在文件的第一個標記以後,定義或取消定義預處理器符號 。咱們也可使用#undef來取消一個符號的定義,來看個例子。
#define DEBUG #undef DEBUG #define ISSAY using System; namespace JustDoIt { class Program { static void Main(string[] args) { #if DEBUG Console.Write("debug."); #endif #if ISSAY Console.Write("hello."); #else Console.Write("you can say nothing."); #endif Console.ReadLine(); } } } //輸出:hello
==============================================================================================
C#有許多名爲預處理器指令的命令。這些命令歷來不會被翻譯爲可執行代碼中的命令,但會影響編譯過程的各個方面。例如,預處理器可禁止編譯器編譯代碼的某一部分。若是計劃發佈兩個版本的代碼,好比基本版本和企業版本,或者針對不一樣的.NET Framework版本進行編碼,就可使用這些指令。在Anthem.NET的代碼中咱們常常能夠看到這種用法。
預處理器指令的開頭都有符號#。
注意:
C#中並無一個像C++那樣的獨立預處理器,所謂的預處理器指令仍由編譯器處理。
下面將對這些指令逐一介紹。
#define能夠定義符號。當將符號用做傳遞給#if指令的表達式時,此表達式的計算結果true。如
#define DEBUG
它告訴編譯器存在給定名稱的符號,在本例中是DEBUG。這個符號不是實際代碼的一部分,只在編譯代碼時存在。
#undef正好相反,它刪除一個符號。
必須把#define和#undef命令放在C#源碼的開頭,即在要編譯的任何代碼以前。它不像C++中那樣能夠定義常數值。
#define自己並沒有大用,它須要配合#if指令使用。
以下代碼:
#define DEBUG int DoSw(double x) { #if DEBUG COnsole.WriteLine("x is"+X); #edif }
這些指令告訴編譯器是否要編譯某個代碼塊。看下面的方法:
static void PrintVersion() { #if V3 Console.WriteLine("Version 3.0"); #elif V2 Console.WriteLine("Version 2.0"); #else Console.WriteLine("Version 1.0"); #endif }
上面的代碼會根據定義的符號來打印不一樣的版本信息。 這種方式成爲條件編譯。
注意:
使用#if不是條件編譯代碼的惟一方式,C#還提供了經過Conditional屬性的機制。
#if和#elif還支持一組邏輯運算符!=,==,!=和|| 。若是符號存在,符號的值被認爲是true,不然爲false,如:
#if V3 || (V2 == true) // if 定義了V3或V2符號...
這也是兩個頗有用的預處理器指令,編譯器遇到它們時,會分別產生警告或錯誤信息。若是遇到#warning指令,會向用戶顯示#warning指令後面的文本。實際上,在VS2005中,IDE會直接將信息標識出來:
而若是編譯器遇到#error,就會當即退出編譯,不會產生IL代碼。
使用這兩個指令能夠檢查#define是不示作錯了什麼事,使用#warning可讓本身想起作什麼事。
#if DEBUG && RELEASE #error "You 've define xxxx!" #ednif #warning "Don't forgot to removexxxxxx!" Console.WriteLine("I have this job");
#region和#endregion指令用於把一段代碼標記爲有指定名稱的一個塊,以下所示:
#region private methods private int x; private int y; #endregion
這兩個指令不會影響編譯過程。但能夠爲VS編輯器所識別,從而使得代碼顯示佈局更爲清晰。
能夠用於改變編譯器在警告和錯誤信息中顯示的文件的名字和行號信息。若是編寫代碼時,在把代碼發給比編譯器前,要使用某些軟件包改變鍵入的代碼,玖可使用者個指令,由於這意味着比編譯器的報告的行號或文件名與文件中的行號或編譯的文件名不匹配。#line指令能夠用於恢復這種匹配也可使用語法#line default 把行號恢復默認。
#line 164 "cORE.CS"
#LINE default
#pragma:爲編譯器提供特殊的指令,說明如何編譯包含雜注的文件。
#pragma warning:可啓用或禁用某些警告。
#pragma checksum:生成源文件的校驗和,以幫助調試ASP.NET頁。
能夠抑制或恢復指定的編譯警告。與命令行選項不一樣,#pragma指令能夠在類和方法上執行,對抑制什麼警告和抑制的時間進行更精細的控制。
#pragma warning disable 169 public class Aclass { int nFiled; }
#pragma warning restore 169
這些預處理指令詳見MSDN:
出處:http://www.bianceng.cn/Programming/csharp/200910/11700.htm