在大型项目中,使用哪种方法更好,以及为什么:

#if DEBUG
    public void SetPrivateValue(int value)
    { ... }
#endif

or

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }

当前回答

对于第一个示例,如果没有定义DEBUG,则SetPrivateValue将不存在于构建中;对于第二个示例,如果没有定义DEBUG,则对SetPrivateValue的调用将不存在于构建中。

对于第一个示例,您还必须使用#if DEBUG包装任何对SetPrivateValue的调用。

对于第二个示例,将省略对SetPrivateValue的调用,但请注意,SetPrivateValue本身仍将被编译。如果您正在构建一个库,那么引用您的库的应用程序仍然可以使用您的函数(如果条件满足),那么这很有用。

如果你想忽略调用并节省被调用者的空间,你可以结合使用这两种技术:

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
    #if DEBUG
    // method body here
    #endif
}

其他回答

好吧,值得注意的是,它们的意思完全不同。

如果没有定义DEBUG符号,那么在第一种情况下SetPrivateValue本身不会被调用…而在第二种情况下,它将存在,但任何编译时不使用DEBUG符号的调用者将省略这些调用。

如果代码及其所有调用者都在同一个程序集中,那么这种区别就不那么重要了——但这意味着在第一种情况下,调用代码也需要使用# If DEBUG。

就我个人而言,我会推荐第二种方法——但你确实需要在脑子里清楚它们之间的区别。

让我们假设您的代码也有一个#else语句,它定义了一个空存根函数,处理Jon Skeet的一个点。这两者之间还有第二个重要的区别。

假设#if DEBUG或Conditional函数存在于被你的主项目可执行文件引用的DLL中。使用#if,将根据库的编译设置执行条件的求值。使用Conditional属性,条件的计算将根据调用程序的编译设置执行。

我有一个SOAP WebService扩展来记录网络流量使用自定义[TraceExtension]。我只在调试版本中使用这个选项,在发布版本中省略。使用#if DEBUG来包装[TraceExtension]属性,从而将其从发布版本中移除。

#if DEBUG
[TraceExtension]
#endif
[System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )]
[ more attributes ...]
public DatabaseResponse[] GetDatabaseResponse( ...) 
{
    object[] results = this.Invoke("GetDatabaseResponse",new object[] {
          ... parmeters}};
}

#if DEBUG
[TraceExtension]
#endif
public System.IAsyncResult BeginGetDatabaseResponse(...)

#if DEBUG
[TraceExtension]
#endif
public DatabaseResponse[] EndGetDatabaseResponse(...)

对于第一个示例,如果没有定义DEBUG,则SetPrivateValue将不存在于构建中;对于第二个示例,如果没有定义DEBUG,则对SetPrivateValue的调用将不存在于构建中。

对于第一个示例,您还必须使用#if DEBUG包装任何对SetPrivateValue的调用。

对于第二个示例,将省略对SetPrivateValue的调用,但请注意,SetPrivateValue本身仍将被编译。如果您正在构建一个库,那么引用您的库的应用程序仍然可以使用您的函数(如果条件满足),那么这很有用。

如果你想忽略调用并节省被调用者的空间,你可以结合使用这两种技术:

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
    #if DEBUG
    // method body here
    #endif
}

通常你会在Program.cs中需要它,在这里你想要决定在非调试代码上运行调试,而在Windows服务中也是如此。因此,我创建了一个只读字段IsDebugMode,并在静态构造函数中设置其值,如下所示。

static class Program
{

    #region Private variable
    static readonly bool IsDebugMode = false;
    #endregion Private variable

    #region Constrcutors
    static Program()
    {
 #if DEBUG
        IsDebugMode = true;
 #endif
    }
    #endregion

    #region Main

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {

        if (IsDebugMode)
        {
            MyService myService = new MyService(args);
            myService.OnDebug();             
        }
        else
        {
            ServiceBase[] services = new ServiceBase[] { new MyService (args) };
            services.Run(args);
        }
    }

    #endregion Main        
}