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

Nea*_*ers 401 c# debugging release compiler-directives

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

在主程序的开头,我有这个代码,它显示"Mode = Debug".我也在最顶端有这两行:

#define DEBUG 
#define RELEASE
Run Code Online (Sandbox Code Playgroud)

我在测试正确的变量吗?

#if (DEBUG)
            Console.WriteLine("Mode=Debug"); 
#elif (RELEASE)
            Console.WriteLine("Mode=Release"); 
#endif
Run Code Online (Sandbox Code Playgroud)

我的目标是根据调试版本和发布模式为变量设置不同的默认值.

psy*_*tik 673

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

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

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

#if DEBUG
    Console.WriteLine("Mode=Debug"); 
#else
    Console.WriteLine("Mode=Release"); 
#endif
Run Code Online (Sandbox Code Playgroud)

不要检查RELEASE

  • 我想补充一点,如果只想检查RELEASE,那么可以这样做:#if!DEBUG (71认同)
  • @Jess,我相信这是Visual Studio的灰色,而不是ReSharper (24认同)
  • @ BobStein-VisiBone请记住我们在这里讨论C#,而不是C.`#ifdef`特定于C/C++的预处理器,C#强制使用`#if`. (22认同)
  • 为什么`#if`而不是`#ifdef`? (3认同)
  • 如何“设置预处理器”? (2认同)

Meh*_*ari 280

默认情况下,如果项目在调试模式下编译,Visual Studio将定义DEBUG,如果项目处于发布模式,则不定义它.默认情况下,RELEASE未在发布模式中定义.使用这样的东西:

#if DEBUG
  // debug stuff goes here
#else
  // release stuff goes here
#endif
Run Code Online (Sandbox Code Playgroud)

如果您只想在发布模式下执行某些操作:

#if !DEBUG
  // release...
#endif
Run Code Online (Sandbox Code Playgroud)

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

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

void Test() {
    PrintLog();
}
Run Code Online (Sandbox Code Playgroud)

  • 很棒的答案,赞赏. (6认同)

Joe*_*orn 193

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

if (System.Diagnostics.Debugger.IsAttached)
{
   //...
}
else
{
   //...
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以在调试模式下编译和部署某些内容,但仍然没有附加调试器.

  • 回过头来做这个而不是使用`#DEBUG`是这个if语句在你的代码中并且总是检查`#DEBUG`的答案在哪里删除了在编译时不适用的代码所以你没有运行时检查和你的.exe(或你编译的任何东西)都较小. (10认同)
  • 谢谢你!我什至还不知道“#defines”是什么,所以这是一个很好的解决方案! (3认同)
  • @用户34660。上述问题的答案是“否”,这对任何人都没有真正的帮助。 (2认同)

Tod*_*son 50

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

所以这就是我的想法(灵感来自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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这样做的好处是不会因Resharper中的重构错误而受到攻击,这些错误会导致基于当前条件设置的代码陷入困境. (3认同)
  • 我喜欢这个,但我想知道为什么不为此而不是服务创建单例实现.它是系统特定的,它可以阻止您不必担心在任何地方注入它.(你能想象一下这个功能的实现会有什么不同吗? (3认同)
  • 嘿,现在,这很有创意.我喜欢你使用属性来设置属性. (2认同)
  • 我想知道为什么“DebuggingService”不是静态类,为什么需要接口?这与将它与 IoC 容器一起使用有关吗? (2认同)

Ale*_*exD 20

bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='
Run Code Online (Sandbox Code Playgroud)

该方法Debug.Assert具有条件属性DEBUG.如果未定义,则消除呼叫和分配 :isDebug = true

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

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


Mat*_*ted 19

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

#define DEBUG  
#define RELEASE 
Run Code Online (Sandbox Code Playgroud)

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

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

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

#if DEBUG
    Console.WriteLine("Debug");
#else
    Console.WriteLine("Release");
#endif
Run Code Online (Sandbox Code Playgroud)


gri*_*rak 10

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

在项目构建属性中定义 DEBUG 常量


McA*_*den 7

删除顶部的定义

#if DEBUG
        Console.WriteLine("Mode=Debug"); 
#else
        Console.WriteLine("Mode=Release"); 
#endif
Run Code Online (Sandbox Code Playgroud)


Loc*_*Guy 7

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;
}
Run Code Online (Sandbox Code Playgroud)


Yrt*_*rth 7

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


小智 6

命名空间

using System.Resources;
using System.Diagnostics;
Run Code Online (Sandbox Code Playgroud)

方法

   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;
    }
Run Code Online (Sandbox Code Playgroud)


ila*_*ans 5

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

您需要注意 PUBLISH Configuration,如下所示:

在此输入图像描述