2009-09-20 71 views
8

我已經在調試.NET 2.0的應用程序看到下面的代碼條件( 「調試」)+#如果DEBUG

[Conditional("DEBUG")] 
void AssertTableExists() { 
    #if DEBUG 
     ... 
    #endif 
} 

是否有任何理由使用#if指令?我的意思是,根據我的理解,只有在DEBUG被定義時纔會調用該方法,所以我在方法體中沒有看到#if的含義。

回答

20

巧合的是,我恰巧在上週的博客上回答你的問題。

http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

#if指令是必要的,如果該方法的主體是指其本身的#if DEBUG指令下聲明實體。例如

#if DEBUG 
static private int testCounter = 1; 
#endif 

[Conditional("DEBUG")] void CheckConsistency() 
{ 
#if DEBUG 
    testCounter++; 
#endif 
... 

如果省略方法體中的#if DEBUG,那麼在發佈版本中不會進行編譯。

9

其實有很多不同之處。 ConditionalAttribute在代碼中看起來更清晰,但它有很多限制,至少比#if有一個優點。

  • 的#if完全從彙編如果沒有定義符號去除代碼。

  • #如果爲您提供了更好的粒度控制 - 你可以圍繞方法或全部方法或類甚至是整個類的某些成員內部的一條線。

  • #如果讓你寫複雜的條件是這樣的:

    #if DEBUG & !NO_NETWORK 
    
  • #如果的#else#elif指令允許更復雜的情況。

  • [條件]只適用於一個單一的整體方法返回空隙

  • [有條件的]將代碼包含到已編譯的程序集中,但刪除對其的所有調用。如果有人引用你的程序集,他會看到用[有條件]標記的方法,並且能夠使用它們 - 這是你不能用#if實現的。

使用反射器打開.Net Framework程序集,找到標記爲條件[「DBG」]的方法並查看它們的用法很有趣。 任何地方,甚至是內部的,都不能在任何地方使用!這是因爲Microsoft編譯.Net版本時沒有定義符號「DBG」,但實際上它們是在開發過程中使用這些方法來調試.Net。

  • 這是不可能有兩個方法與帶有[條件]相同簽名但你可以#如果實現它。

作爲最後一個音符,我必須說,條件編譯有時扮演邪惡的遊戲,當你在調試完全不同的行爲和發佈的版本,你只有瞭解它,你部署你的代碼,用戶開始抱怨了。因此,根據經驗,儘量避免用#if改變行爲,只用它來改變輸入數據。

下面是一個使用#if的例子 - 調試版本和發行版本的不同應用程序配置。

static string ConnectionString 
{ 
#if DEBUG 
    get { return "<debug connection string>"; } 
#else 
    get { return "<release connection string>"; } 
#endif 
} 
+1

ConditionalAttribute也可以應用於其他屬性定義;如果條件不滿足,則在編譯過程中不會應用標記的屬性 – thecoop 2009-09-26 09:26:25