492

在解决方案属性中,我将配置设置为我唯一的项目的“发布”。

在主程序的开头,我有这段代码,它显示“Mode=Debug”。我在最上面也有这两行:

#define DEBUG 
#define RELEASE

我在测试正确的变量吗?

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

我的目标是根据调试与发布模式为变量设置不同的默认值。

4

15 回答 15

807

DEBUG/_DEBUG应该已经在 VS 中定义了。

删除#define DEBUG代码中的。在该特定构建的构建配置中设置预处理器。

它打印“Mode=Debug”的原因是因为你#define然后跳过了elif.

正确的检查方法是:

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

不要检查RELEASE.

于 2010-01-20T19:05:42.430 回答
328

默认情况下,如果项目在 Debug 模式下编译,Visual Studio 会定义 DEBUG,如果它处于 Release 模式,则不会定义它。默认情况下,RELEASE 未在 Release 模式下定义。使用这样的东西:

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

如果你只想在发布模式下做某事:

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

此外,值得指出的是,您可以[Conditional("DEBUG")]在返回的方法上使用属性,void以便仅在定义了某个符号时才执行它们。如果未定义符号,编译器将删除对这些方法的所有调用:

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

void Test() {
    PrintLog();
}
于 2010-01-20T19:04:33.103 回答
245

我更喜欢像这样检查它而不是寻找#define指令:

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

需要注意的是,您当然可以在调试模式下编译和部署某些东西,但仍然没有附加调试器。

于 2010-01-20T19:09:59.907 回答
59

我不是#if 东西的忠实拥护者,特别是如果你将它散布在你的代码库中,因为如果你不小心,它会给你带来调试构建通过但发布构建失败的问题。

所以这就是我想出的(灵感来自#ifdef in C#):

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;
    }
}
于 2013-03-08T07:16:17.727 回答
31
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

该方法Debug.Assert具有条件属性DEBUG。如果未定义,则取消调用和分配isDebug = true

如果定义了符号,则包含调用;否则,调用(包括调用参数的评估)将被省略。

如果DEBUG已定义,isDebug则设置为true(并传递给Debug.Assert,在这种情况下不执行任何操作)。

于 2014-01-28T22:24:54.297 回答
21

如果您尝试使用为构建类型定义的变量,则应删除这两行...

#define DEBUG  
#define RELEASE 

...这些将导致#if (DEBUG)始终为真。

RELEASE也没有默认的条件编译符号。如果要定义一个转到项目属性,请单击Build选项卡,然后将 RELEASE 添加到General标题下的Conditional compilation symbols文本框中。

另一种选择是这样做......

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif
于 2010-01-20T19:03:47.457 回答
11

请务必在 Project Build Properties 中定义 DEBUG 常量。这将启用#if DEBUG. 我没有看到预定义的 RELEASE 常量,因此这可能意味着任何不在 DEBUG 块中的东西都是 RELEASE 模式。

在 Project Build Properties 中定义 DEBUG 常量

于 2018-07-11T18:26:44.623 回答
8

删除顶部的定义

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif
于 2010-01-20T19:07:10.773 回答
8

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;
}
于 2014-04-23T14:45:25.157 回答
7

命名空间

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;
    }
于 2012-05-07T14:13:23.890 回答
3

一个可以为您节省大量时间的提示 - 不要忘记,即使您debug在构建配置下进行选择(在 vs2012/13 菜单上,它位于 BUILD => CONFIGURATION MANAGER 下) - 这还不够。

您需要注意 PUBLISH Configuration,例如:

在此处输入图像描述

于 2015-07-02T05:53:28.040 回答
2

这里值得注意的是,有条件地执行代码之间最显着的区别之一#if DEBUGif(System.Diagnostics.Debugger.IsAttached)编译器指令会更改已编译的代码。也就是说,如果您在一个#if DEBUG/#else/#endif条件块中有两条不同的语句,则编译代码中只会出现其中一条。这是一个重要的区别,因为它允许您执行诸如有条件地将方法定义编译为public void mymethod()internal void mymethod()取决于构建类型,例如,您可以在调试构建上运行不会破坏生产构建访问控制的单元测试,或者有条件地编译调试构建中的辅助函数,如果它们违反安全性,则不会出现在最终代码中他们应该以某种方式逃到野外。IsAttached另一方面,该属性不会影响已编译的代码。两组代码都在所有构建中 -IsAttached条件只会影响执行的内容。这本身可能会带来安全问题。

于 2020-07-31T13:18:05.217 回答
0

我不得不考虑一个更好的方法。我突然意识到#if 块是其他配置中的有效注释(假设DEBUGor RELEASE; 但对于任何符号都是如此)

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");
        }
于 2019-07-12T05:08:14.140 回答
0

删除定义并检查条件是否处于调试模式。您不需要检查指令是否处于发布模式。

像这样的东西:

#if DEBUG
     Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
于 2019-07-22T23:48:06.720 回答
-1

由于这些 COMPILER 指令的目的是告诉编译器不要包含代码、调试代码、beta 代码,或者可能是所有最终用户都需要的代码,除了那些广告部门,即你想要的#Define AdDept能够根据您的需要包括或删除它们。例如,如果非 AdDept 合并到 AdDept 中,则无需更改源代码。然后所有需要做的就是在现有版本的程序的编译器选项属性页面中包含#AdDept 指令,然后编译并哇!合并后的程序代码活跃起来!

您可能还希望对尚未准备好迎接黄金时间或在代码中无法在代码中处于活动状态的新进程使用声明性,直到发布它。

无论如何,我就是这样做的。

于 2013-09-14T22:46:35.793 回答