簡體   English   中英

用於調試與發布的 C# if/then 指令

[英]C# if/then directives for debug vs release

在解決方案屬性中,我將我的一個且唯一的項目的配置設置為“發布”。

在主程序的開頭,我有這個代碼,它顯示“模式=調試”。 我在最頂部也有這兩行:

#define DEBUG 
#define RELEASE

我在測試正確的變量嗎?

#if (DEBUG)
            Console.WriteLine("Mode=Debug"); 
#elif (RELEASE)
            Console.WriteLine("Mode=Release"); 
#endif

我的目標是根據調試與發布模式為變量設置不同的默認值。

DEBUG / _DEBUG應該已經在 VS 中定義了。

刪除代碼中的#define DEBUG 在該特定構建的構建配置中設置預處理器。

它打印 "Mode=Debug" 的原因是因為你的#define然后跳過了elif

正確的檢查方法是:

#if DEBUG
    Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif

不要檢查RELEASE

默認情況下,如果項目在調試模式下編譯,Visual Studio 定義 DEBUG,如果項目在發布模式下不定義它。 默認情況下,在 Release 模式下未定義 RELEASE。 使用這樣的東西:

#if DEBUG
  // debug stuff goes here
#else
  // release stuff goes here
#endif

如果你只想在發布模式下做一些事情:

#if !DEBUG
  // release...
#endif

此外,值得指出的是,您可以在返回void方法上使用[Conditional("DEBUG")]屬性,以便僅在定義了某個符號時才執行它們。 如果未定義符號,編譯器將刪除對這些方法的所有調用:

[Conditional("DEBUG")]
void PrintLog() {
    Console.WriteLine("Debug info");
}

void Test() {
    PrintLog();
}

我更喜歡像這樣檢查它而不是尋找#define指令:

if (System.Diagnostics.Debugger.IsAttached)
{
   //...
}
else
{
   //...
}

需要注意的是,您當然可以在調試模式下編譯和部署某些東西,但仍然沒有附加調試器。

我不是#if 東西的忠實粉絲,特別是如果你把它散布在你的代碼庫中,因為如果你不小心,它會給你帶來調試構建通過但發布構建失敗的問題。

所以這就是我想出的(靈感來自C# 中#ifdef ):

public interface IDebuggingService
{
    bool RunningInDebugMode();
}

public class DebuggingService : IDebuggingService
{
    private bool debugging;

    public bool RunningInDebugMode()
    {
        //#if DEBUG
        //return true;
        //#else
        //return false;
        //#endif
        WellAreWe();
        return debugging;
    }

    [Conditional("DEBUG")]
    private void WellAreWe()
    {
        debugging = true;
    }
}
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

方法Debug.Assert具有條件屬性DEBUG 如果未定義,則取消調用和賦值isDebug = true

如果定義了符號,則包括調用; 否則,調用(包括調用參數的評估)將被省略。

如果定義了DEBUG ,則isDebug設置為true (並傳遞給Debug.Assert ,在這種情況下它什么都不做)。

如果您嘗試使用為構建類型定義的變量,則應刪除這兩行...

#define DEBUG  
#define RELEASE 

...這些將導致#if (DEBUG)始終為真。

RELEASE也沒有默認的條件編譯符號。 如果要定義一個轉到項目屬性,請單擊“構建”選項卡,然后將 RELEASE 添加到“常規”標題下的“條件編譯符號”文本框。

另一種選擇是這樣做......

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif

確保在 Project Build Properties 中定義 DEBUG 常量。 這將啟用#if DEBUG 我沒有看到預定義的 RELEASE 常量,因此這可能意味着不在 DEBUG 塊中的任何內容都是 RELEASE 模式。

在項目構建屬性中定義 DEBUG 常量

刪除頂部的定義

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif

Tod Thomson 對答案的輕微修改(混蛋?)版本作為靜態函數而不是單獨的類(我希望能夠在我已經包含的 viewutils 類的 WebForm 視圖綁定中調用它)。

public static bool isDebugging() {
    bool debugging = false;

    WellAreWe(ref debugging);

    return debugging;
}

[Conditional("DEBUG")]
private static void WellAreWe(ref bool debugging)
{
    debugging = true;
}

命名空間

using System.Resources;
using System.Diagnostics;

方法

   private static bool IsDebug()
    {
        object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
        if ((customAttributes != null) && (customAttributes.Length == 1))
        {
            DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
            return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
        }
        return false;
    }

一個可以為您節省大量時間的提示——不要忘記,即使您在構建配置下選擇debug (在 vs2012/13 菜單上,它在 BUILD => CONFIGURATION MANAGER 下)——這還不夠。

您需要注意 PUBLISH Configuration ,例如:

在此處輸入圖片說明

這里值得注意的是,基於#if DEBUGif(System.Diagnostics.Debugger.IsAttached)條件執行代碼之間最顯着的區別之一是編譯器指令更改了編譯的代碼 也就是說,如果在#if DEBUG/#else/#endif條件塊中有兩個不同的語句,則編譯代碼中只會出現其中一個 這是一個重要的區別,因為它允許您做一些事情,例如有條件地編譯方法定義為public void mymethod()internal void mymethod()取決於構建類型,以便您可以,例如,在調試構建上運行單元測試不會破壞對生產版本的訪問控制,或者有條件地編譯調試版本中的輔助函數,如果它們會以某種方式違反安全性,則不會出現在最終代碼中。 另一方面, IsAttached屬性不會影響已編譯的代碼。 兩組代碼都在所有構建中 - IsAttached條件只會影響執行的內容 這本身就可能存在安全問題。

由於這些編譯器指令的目的是告訴編譯器不要包含所有最終用戶所需的代碼、調試代碼、測試版代碼或可能的代碼,除了廣告部門,即您想要的#Define AdDept能夠根據您的需要包含或刪除它們。 例如,如果非 AdDept 合並到 AdDept,則無需更改您的源代碼。 然后所有需要做的就是在現有版本程序的編譯器選項屬性頁面中包含#AdDept 指令,然后進行編譯和哇啦! 合並后的程序代碼活躍起來!

您可能還想對尚未准備好迎接黃金時段的新流程或在發布之前無法在代碼中處於活動狀態的新流程使用聲明。

無論如何,這就是我的方式。

我得想一個更好的辦法。 我突然意識到#if 塊在其他配置中是有效的注釋(假設DEBUGRELEASE ;但對於任何符號都是如此)

public class Mytest
    {
        public DateTime DateAndTimeOfTransaction;
    }

    public void ProcessCommand(Mytest Command)
        {
            CheckMyCommandPreconditions(Command);
            // do more stuff with Command...
        }

        [Conditional("DEBUG")]
        private static void CheckMyCommandPreconditions(Mytest Command)
        {
            if (Command.DateAndTimeOfTransaction > DateTime.Now)
                throw new InvalidOperationException("DateTime expected to be in the past");
        }

刪除定義並檢查條件是否處於調試模式。 您不需要檢查指令是否處於發布模式。

像這樣的東西:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM