ChatGPT解决这个技术问题 Extra ChatGPT

用于调试与发布的 C# if/then 指令

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

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

#define DEBUG 
#define RELEASE

我在测试正确的变量吗?

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

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

您正在定义调试和发布。

S
StayOnTarget

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

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

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

正确的检查方法是:

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

不要检查 RELEASE


我想补充一点,如果只想检查 RELEASE,那么可以这样做:#if !DEBUG
为什么是 #if 而不是 #ifdef
@BobStein-VisiBone 请记住,我们在这里谈论的是 C#,而不是 C。#ifdef 特定于 C/C++ 的预处理器,C# 要求使用 #if
@Jess,我相信这是 Visual Studio 做的变灰,而不是 ReSharper
如何“设置预处理器”?
m
mmx

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

很棒的答案,赞赏。
J
Joel Coehoorn

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

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

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


谢谢!我什至还不知道“#defines”是什么,所以这是一个很好的解决方案!
我的情况是,这正是我想要的。我实际上想知道我是否连接了调试器,因为我知道如果我连接了调试器,我不想执行一些代码。这太棒了!
如果个人喜欢在调试不应该持续的代码的情况下使用 #IF DEBUG。对于生产代码,我同意使用上述内容。
这样做而不是使用 #DEBUG 的缺点是这个 if 语句在您的代码中,并且总是检查 #DEBUG 答案在哪里删除了在编译时不适用的代码,因此您没有运行-time 检查并且您的 .exe(或您编译的任何内容)更小。
@用户34660。上述问题的答案是“不”,这对任何人都没有帮助。
C
Community

我不是#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;
    }
}

嘿嘿,这真是太有创意了。我喜欢你使用属性来设置属性。
这样做的好处是不会受到 Resharper 中的重构错误的影响,这些错误可能会根据当前的条件设置弄乱您的代码。
我喜欢这个,但我想知道为什么不为此创建一个单例实现而不是一个服务。它是特定于系统的,它使您不必担心到处注入它。 (你能想象这个功能的实现会有什么不同的场景吗?
实际上,我现在正在使用的一个类中有一个单例和服务实现,因此您可以选择使用它的方式......当然,服务实现的好处是更容易“存根”,所以您可以测试两个代码路径...
我想知道为什么 DebuggingService 不是静态类以及为什么需要接口?这与将其与 IoC 容器一起使用有关吗?
A
AlexD
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='

方法 Debug.Assert 具有条件属性 DEBUG。如果未定义,则调用和赋值 isDebug = trueeliminated

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

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


这也是一个非常有创意的解决方案。 :)
好的。对于需要在 Debug 和 Release 之间更改的迭代变量... var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
M
Matthew Whited

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

#define DEBUG  
#define RELEASE 

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

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

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

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

C
Community

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

https://i.stack.imgur.com/jD7cV.png


M
McAden

删除顶部的定义

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

E
Ehsan Enaloo

命名空间

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

L
LocalPCGuy

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

i
ilans

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

您需要注意 PUBLISH Configuration,例如:

https://i.stack.imgur.com/AOaGO.png


Y
Yrth

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


H
Hasitha Jayawardana

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

A
Anderson Ribeiro

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

像这样的东西:

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

m
mrMagik3805

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

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

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