Visual Studio 2008能够进行C#的条件编译吗?

5

在“生成”菜单下的“配置管理器”中,

有没有一种方法可以注释我的C#代码,使得在调试模式下解除注释的代码不会被编译,但是如果我将其改为发布模式,则可以编译?

为什么我想要这个?我想要在发布模式下编译代码,但在调试模式下不编译的原因是,我有一些代码无法从我的开发PC工作(发送电子邮件等来自我的主机的代码)。

我希望这是自动完成的,而不是在发布之前运行回我的代码并取消注释行。


你要查找的术语是“条件编译”。 - Richard
2
从您的更新中,我认为条件编译并不是您真正想要的。这是您所要求的,但不是您所需要的。您需要一个在开发环境下运行的配置,另一个在QA中运行,另一个在生产中运行。我会倾向于使用配置或面向对象的解决方案来解决这个问题。 - Jeff Fritz
啊啊啊,"条件编译"……我想不起来这个术语了。 - Chaddeus
@Jeff,我完全同意。这对我来说就像是一种过早的优化。 - Dave Markle
3
并不是优化,只是有几行代码不能在调试模式下运行,因为它们无法正常工作并会导致异常。我不想在发布前去取消对这些代码的注释。 - Chaddeus
4个回答

10

你可以在方法上使用条件属性(而不是单独的代码行)来实现这个目的。

例如,以下内容只会在DEBUG版本中编译。

[Conditional("DEBUG")]
public void MyMethod()
{
    // Do Stuff
}

在项目设置中已经指定了DEBUG符号。对于发布版本,您需要创建自己的符号,例如“RELEASE”,这样您就可以执行以下操作:

[Conditional("RELEASE")]
public void MyMethod()
{
    // Do Stuff
}

然而,我建议您退一步,从更高的层次重新审视您的问题,因为我不会真正推荐这种解决方案。


1
虽然不是我想要的直接解决方案,但这也是很好的知识。谢谢。 - Chaddeus

10

你可能在寻找类似于这样的东西:

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

如果你只关心发布模式,你可以使用:

#if !DEBUG
     Console.WriteLine("Release Mode");
#endif

2
我认为这个解决方案和我的一样存在同样的问题。我不建议使用它。我建议将问题作为一个整体来看,看看是否有其他方法来解决更大的问题。在代码中有很多#if语句或条件属性会给任何维护程序员(甚至是你自己几个月后)带来很多困惑,这是确保的。 - Colin Mackay
2
为什么你认为DEBUG符号被错误使用了呢?它默认添加到每个项目中,并且框架已经准备好使用它,所以肯定是有意使用的。我确实觉得有点不寻常,你只在发布模式下编译某些代码而不在调试模式下编译(通常是相反的),但在发布模式和调试模式之间编译不同的代码是环境的一个有意义和有用的特性。 - BlueMonkMN
偶尔使用条件编译标志没有问题。我同意,当你看到超过一小部分时,会感到混乱。 - user2189331
2
我理解你的顾虑。在这种情况下,我只需要使用几次。只有几行代码尝试从我的主机发送电子邮件 - 但是从我的开发框中无法工作。我只是不想在发布之前再回到我的代码中取消注释。谢谢! - Chaddeus
+1,这正是我需要的。在我的情况下,我通过附加到“Application.ThreadException”事件来处理未处理的异常,并在一个漂亮的窗体中显示一个发送按钮,以便在1次点击中将错误发送到电子邮件。然而,在调试模式下,任何异常都不会停止调试,只会显示该表单。这就是为什么我只需要使用“!DEBUG”来附加到事件并显示该表单。 - CallMeLaNN
显示剩余3条评论

4
我会尝试使用面向对象的技术来解决你的问题。使用依赖注入,我会构建一个执行必要调试操作的类。
例如:
```html

像这样:

```
public class MyClass {

    public MyClass(IDoOtherStuff stuffToDo) {
        DoOtherStuff = stuffToDo;
    }

    private IDoOtherStuff DoOtherStuff { get; set; }

    public void Do() {
        DoOtherStuff.BeforeDo();

        // Blah blah blah..

        DoOtherStuff.AfterDo();
    }
}

public interface IDoOtherStuff {
    void BeforeDo();
    void AfterDo();
}

public class DebugOtherStuff : IDoOtherStuff {
    public void BeforeDo() {
        Debug.WriteLine("At the beginning of Do");
    }

    public void AfterDo() {
        Debug.WriteLine("At the end of Do");
    }
}

public class ReleaseOtherStuff : IDoOtherStuff {
    public void BeforeDo() { }
    public void AfterDo() { }
}

现在,你可以使用控制反转容器,如WindsorUnityNinjectSpring.NET来配置您的开发环境和发布环境。

+1 对 DI(依赖注入)作为解决方案的支持,尽管它可能不是这个问题的正确方式,但我相信它是大多数条件编译问题的答案...而且也讲得非常好。 - Martin

-3

我可能错了,但我认为编译器会忽略注释。如果我使用.NET Reflector查看我的汇编代码,我看不到我知道存在的任何注释。

BlueMonkMN的方法可以根据编译模式运行不同的代码。

如果您想要根据使用的编译模式(和其他变量)运行不同的代码,请查看PostSharp。它是一个后编译编译器,可以为您的程序集添加和删除代码。

示例用法: - 我喜欢为我的项目提供详细的调试和跟踪信息。 - 我讨厌在每个方法结果或方法调用之后加上printtrace.write语句,因为这些额外的调试代码会遮盖执行工作的函数。

您可以配置PostSharp动态创建此额外的调试信息!进行一些配置调整,您就可以打印每个函数调用以及每个调用的结果(包括变量内容)。这使得跟踪程序逻辑流程非常容易。


1
重新阅读问题。他想要条件编译,但不知道它的存在。 - John Saunders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接