C#if / then指令用于debug和release

时间:2010-01-20 19:01:12

标签: c# debugging release compiler-directives

在解决方案属性中,我将Configuration设置为“release”,用​​于我唯一的项目。

在主程序开始时,我有这个代码,它显示“Mode = Debug”。 我也在最顶端有这两行:

#define DEBUG 
#define RELEASE

我在测试正确的变量吗?

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

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

15 个答案:

答案 0 :(得分:638)

删除代码中的#define DEBUG。在该特定构建的构建配置中设置预处理器(DEBUG / _DEBUG应该已在VS中定义)。

打印“Mode = Debug”的原因是因为#define,然后跳过elif

另外,正确的检查方法是:

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

不要检查RELEASE

答案 1 :(得分:270)

默认情况下,如果项目在调试模式下编译,Visual Studio将定义DEBUG,如果项目处于发布模式,则不定义它。默认情况下,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();
}

答案 2 :(得分:181)

我更喜欢像这样查看#defines:

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

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

答案 3 :(得分:48)

我不是#if的忠实粉丝,特别是如果你把它全部传播到你的代码库中,因为它会给你带来Debug构建通过的问题,但如果你不小心,Release版本会失败。

所以这就是我的想法(灵感来自#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;
    }
}

答案 4 :(得分:20)

bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

方法Debug.Assert具有条件属性DEBUG。如果未定义,则呼叫和分配 isDebug = trueeliminated

  

如果定义了符号,则包含呼叫;否则,省略呼叫(包括对呼叫参数的评估)。

如果定义了DEBUG,则isDebug设置为true(并传递给Debug.Assert,在这种情况下无效。)

答案 5 :(得分:18)

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

#define DEBUG  
#define RELEASE 

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

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

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

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

答案 6 :(得分:7)

删除顶部的定义

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

答案 7 :(得分:6)

Tod Thomson作为静态函数而不是单独的类稍微修改(bastardized?)版本的答案(我希望能够从我已经包含的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;
}

答案 8 :(得分:4)

名称空间

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;
    }

答案 9 :(得分:3)

可能为您节省大量时间的提示 - 即使您在构建配置下选择class B{abstract class C{abstract void method();}} public class F extends B.C{ F(B b){ b.super(); } void method(){ System.out.println("Hello World"); } public static void main(String[] args){ B b = new B(); F f = new F(b); f.method(); } } ,也不要忘记(在vs2012 / 13菜单上,它在BUILD =>下;配置管理员) - 这还不够。

您需要注意发布debug,因此:

enter image description here

答案 10 :(得分:3)

确保在“项目构建”属性中定义DEBUG常量。这将启用#if DEBUG。我没有看到预定义的RELEASE常量,因此这可能意味着不在DEBUG块中的任何内容都是RELEASE模式。

Define DEBUG constant in Project Build Properties

答案 11 :(得分:0)

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

您可能还希望为新进程使用声明,该进程尚未准备好进入黄金时段,或者在代码发布之前无法在代码中处于活动状态。

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

答案 12 :(得分:0)

我必须考虑一种更好的方法。我突然意识到#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");
        }

答案 13 :(得分:0)

删除定义,并检查条件是否处于调试模式。您无需检查该指令是否处于释放模式。

类似这样的东西:

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

答案 14 :(得分:0)

在这里值得注意的是,基于#if DEBUGif(System.Diagnostics.Debugger.IsAttached)的有条件执行的代码之间最显着的差异之一是编译器指令更改了已编译的代码 。也就是说,如果在#if DEBUG/#else/#endif条件块中有两个不同的语句,则其中只有一个会出现在编译后的代码中。这是一个重要的区别,因为它允许您执行一些操作,例如根据构建类型将条件编译方法定义分为public void mymethod()internal void mymethod(),以便例如在调试版本中运行单元测试不会破坏生产版本上的访问控制,也不会在调试版本中有条件地编译帮助程序功能,如果这些功能会以某种方式破坏安全性的话,这些功能将不会出现在最终代码中。另一方面,IsAttached属性不会影响已编译的代码。两组代码都在所有版本中-IsAttached条件仅会影响执行。这本身可能会带来安全问题。