【问题标题】:How do I conditionally enable attributes in C#? "#if DEBUG" isn't working如何在 C# 中有条件地启用属性? “#if DEBUG”不起作用
【发布时间】:2010-11-02 03:47:04
【问题描述】:

当我编写时,C# 中可靠的旧预处理器指令似乎工作得很好:

#if DEBUG
...
(Some code)
...
#endif

但是,包含在条件块中的属性似乎继续得到处理,我收到错误指示。例如,在条件块中包围 [AssemblyVersion(...)] 似乎没有任何影响。

我可以详细说明为什么我们要有条件地忽略 [AssemblyVersion(..)],但这无关紧要。有什么想法吗?

【问题讨论】:

  • 对于此行为的示例,定义两个 AssemblyVersion 属性,并将一个放在条件“#if DEBUG”块内。
  • 它被称为预处理指令,在 C# 中它实际上是由编译器处理的。
  • 如果您有两个 AssemblyVersion 属性,其中一个位于“#if DEBUG”块内,我希望另一个位于“#else”和“#endif”之间?
  • 它是在构建时通过自动构建过程在发布配置中动态添加的。顺便说一句,这是 VS 2008。我从头开始创建的另一个项目不会出现这个问题。这很奇怪。
  • 你能发布一个生成输出的例子吗?

标签: c# attributes c-preprocessor


【解决方案1】:

这对我来说是正确的。在我的 AssemblyInfo.cs 文件中,我有以下内容:

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif

在 Reflector 中查看编译后的程序集,我看到了正确的属性。

您应该确保您的 DEBUG 符号仅在项目 properties 中定义,而不是在代码中的任何其他地方定义为实际的#define DEBUG 指令。如果您直接在代码中定义它,它将仅对该文件有效,而不是整个项目。在项目属性中定义它会导致它对整个项目生效。

【讨论】:

  • 这很奇怪。使用一个简单的控制台应用程序,它可以正常工作(选择发布模式,它确实忽略了#if DEBUG 块中的属性!).. 做更多的研究......有问题的项目是一个类库。会解决这个问题的......
  • 我从中提取示例代码的项目也是一个类库,因此对行为没有影响。我见过#if DEBUG 不起作用但#if Debug 起作用的情况,主要是由于定义不正确。检查您的项目属性并确保您没有任何#define 指令。
  • @ScottDorman 有没有办法使用 [Conditional("DEBUG")] 来代替?
【解决方案2】:

我想通了!我忽略了一条关键信息:它是一个工作流项目(Guid {14822709-B5A1-4724-98CA-57A101D1B079})。事实证明,工作流项目类型存在错误,特别是构建文件中包含的 Workflow.Targets 文件。

似乎预处理器的行为就像定义了 DEBUG 常量一样。您可以通过创建工作流项目并将其添加到 AssemblyInfo 文件来重现该问题:

#if DEBUG
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif

然后尝试发布版本。 我将此提交给 MS:https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466440

最好的问候! -肖恩

【讨论】:

  • 您应该已经编辑了原件并添加了此信息。从技术上讲,这不是正确的答案,因为问题被错误地问了:)
【解决方案3】:

您确定不是在发布模式下构建吗?

【讨论】:

  • 是发布模式。在这种情况下,在发布配置中,“#if DEBUG”中的块仍在处理中。
【解决方案4】:

更简单 - 您可以使用元数据标签 [Conditional] 标记您的调试函数:

#define DEBUG1

...

public static void PrintText1(string txt)   {
    Console.Write("This is PrintText2\n");
}

[Conditional("DEBUG1")]
public static void PrintText2(string txt)   {
    Console.Write("This is PrintText2\n");
}

[STAThread]
static void Main(string[] args)    {
    PrintText1("This is the unconditional method");
    PrintText2("This function will be called only if 'DEBUG1' is defined");
}

试试吧!

另外,我注意到#define 只存在于它定义的文件的上下文中,例如从另一个未定义调试的文件调用 PrintText2 将不会执行。这也适用于相反的方式:

[Conditional("DEBUG1")]
public static void ConditionedPrint(string txt) {
    Console.Write("This is PrintText2\n");
}

public static void UnconditionedPrint(string txt)     {
    ConditionedFunc(txt);
}

UnconditionFunc 将打印 "This is PrintText2\n" iff (当且仅当) #define DEBUG1 已在 this 文件中定义,而与其他文件无关。

还有 System.Diagnostics.Debug,但我不确定它的作用。

【讨论】:

  • 这适用于接受属性的事物,但属性本身需要是有条件的。它适用于一个简单的项目,因此它与项目相关。感谢您的提示!这是一个整洁的新属性。
  • 哦,抱歉,我没有注意到您希望元数据标签也有条件。我可以告诉你的是,C# 中的#define 只存在于同一个文件的上下文中,所以这可能是原因。 VS 应该标出不会被编译的行,所以当它按照你想要的方式工作时,你应该注意到视觉上的差异。
  • 我想这才有意义
【解决方案5】:

要跟进@yoyoyoyosef 的评论回答,您需要查看项目的属性页面。

您将在 Build 菜单的 General 标题下看到,确保未选中“Define DEBUG constant”复选框。

此值会根据“构建”菜单顶部的“配置”选项(下拉菜单)而变化。

【讨论】:

    猜你喜欢
    • 2020-03-11
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 2014-03-21
    相关资源
    最近更新 更多