在解决方案属性中,我将配置设置为我唯一的项目的“发布”。
在主程序的开头,我有这段代码,它显示“Mode=Debug”。我在最上面也有这两行:
#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
。
默认情况下,如果项目在 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();
}
我更喜欢像这样检查它而不是寻找 #define
指令:
if (System.Diagnostics.Debugger.IsAttached)
{
//...
}
else
{
//...
}
需要注意的是,您当然可以在调试模式下编译和部署某些东西,但仍然没有附加调试器。
#IF DEBUG
。对于生产代码,我同意使用上述内容。
#DEBUG
的缺点是这个 if 语句在您的代码中,并且总是检查 #DEBUG
答案在哪里删除了在编译时不适用的代码,因此您没有运行-time 检查并且您的 .exe(或您编译的任何内容)更小。
我不是#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;
}
}
DebuggingService
不是静态类以及为什么需要接口?这与将其与 IoC 容器一起使用有关吗?
bool isDebug = false;
Debug.Assert(isDebug = true); // '=', not '=='
方法 Debug.Assert
具有条件属性 DEBUG
。如果未定义,则调用和赋值 isDebug = true
为 eliminated:
如果定义了符号,则包含调用;否则,调用(包括调用参数的评估)将被省略。
如果定义了 DEBUG
,则将 isDebug
设置为 true
(并传递给 Debug.Assert
,在这种情况下不执行任何操作)。
var iterations = 10; Debug.Assert((iterations = Int32.MaxValue) > 0);
如果您尝试使用为构建类型定义的变量,则应删除这两行...
#define DEBUG
#define RELEASE
...这些将导致#if (DEBUG) 始终为真。
RELEASE 也没有默认的条件编译符号。如果要定义一个转到项目属性,请单击 Build 选项卡,然后将 RELEASE 添加到 General 标题下的 Conditional compilation symbols 文本框中。
另一种选择是这样做......
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
请务必在 Project Build Properties 中定义 DEBUG 常量。这将启用 #if DEBUG
。我没有看到预定义的 RELEASE 常量,因此这可能意味着任何不在 DEBUG 块中的东西都是 RELEASE 模式。
https://i.stack.imgur.com/jD7cV.png
删除顶部的定义
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
命名空间
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;
}
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;
}
一个可以为您节省大量时间的提示 - 不要忘记,即使您在构建配置下选择 debug
(在 vs2012/13 菜单上,它位于 BUILD => CONFIGURATION MANAGER 下) - 这还不够。
您需要注意 PUBLISH Configuration
,例如:
https://i.stack.imgur.com/AOaGO.png
此处值得注意的是,基于 #if DEBUG
与 if(System.Diagnostics.Debugger.IsAttached)
有条件地执行代码之间最显着的区别之一是编译器指令更改了已编译的代码。也就是说,如果您在 #if DEBUG/#else/#endif
条件块中有两个不同的语句,则只有 一个 会出现在编译的代码中。这是一个重要的区别,因为它允许您执行诸如根据构建类型有条件地将方法定义编译为 public void mymethod()
与 internal void mymethod()
之类的事情,这样您就可以在不会中断访问的调试构建上运行单元测试控制生产构建,或有条件地编译调试构建中的辅助函数,如果它们在逃逸时会以某种方式违反安全性,则不会出现在最终代码中。另一方面,IsAttached
属性不会影响已编译的代码。两组代码都在所有构建中 - IsAttached
条件只会影响执行的内容。这本身可能会带来安全问题。
我不得不考虑一个更好的方法。我突然意识到#if 块是其他配置中的有效注释(假设 DEBUG
或 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");
}
删除定义并检查条件是否处于调试模式。您不需要检查指令是否处于发布模式。
像这样的东西:
#if DEBUG
Console.WriteLine("Mode=Debug");
#else
Console.WriteLine("Mode=Release");
#endif
由于这些 COMPILER 指令的目的是告诉编译器不要包含代码、调试代码、beta 代码,或者可能是所有最终用户都需要的代码,除了那些广告部门,即你想要的#Define AdDept能够根据您的需要包括或删除它们。例如,如果非 AdDept 合并到 AdDept 中,则无需更改源代码。然后所有需要做的就是在现有版本的程序的编译器选项属性页面中包含#AdDept 指令,然后编译并哇!合并后的程序代码活跃起来!
您可能还希望对尚未准备好迎接黄金时间或在代码中无法在代码中处于活动状态的新进程使用声明性,直到发布它。
无论如何,我就是这样做的。
#if
而不是#ifdef
?#ifdef
特定于 C/C++ 的预处理器,C# 要求使用#if
。