在C#中保持调试字符串不在构建中

Pol*_*ial 2 c# logging c-preprocessor

在编写代码时,我经常在代码中放置调试消息.调试消息由记录器类处理,记录器类以调试模式将消息输出到文件,并在释放模式下丢弃它们.

它看起来像这样:

class Logger : IDisposable
{
    private StreamWriter m_Logger = null;

    public void Start(string logFile)
    {
        m_Logger = new StreamWriter(logFile);
        m_Logger.AutoFlush = true;
    }

    public void Dispose()
    {
        if (m_Logger != null) m_Logger.Dispose();
    }

    public void WriteLine(string message)
    {
        if (m_Logger != null) m_Logger.WriteLine(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

实例在启动时创建,可从Program类中访问.然后我检查这样的调试:

#if DEBUG
Program.Log.Start("app.log");
#endif
Run Code Online (Sandbox Code Playgroud)

这很好用,因为它在调试模式下转储调试信息,而不是在发布模式下.但是,如果我通过实用程序运行发布可执行文件strings,我仍然可以看到调试字符串.我宁愿让它们完全脱离发布版本,以帮助防止逆向工程.

到目前为止,我发现的唯一解决方案是将所有调试消息包装在预处理器条件中:

// < some code here >
#if DEBUG
Program.Log.WriteLine("Some debug message.");
#endif
// < more code here >
Run Code Online (Sandbox Code Playgroud)

这非常乏味和丑陋.我的第一个想法是使用某种预处理器宏,但C#不支持它们.有没有比我现在使用的更优雅的解决方案?

Tis*_*sho 6

为避免在每次WriteLine调用中使用#if- #endif,请尝试在记录器方法本身上使用ConditionalAttribute:

[Conditional("DEBUG")]
public void WriteLine(string message)
{
    if (m_Logger != null) m_Logger.WriteLine(message);
}
Run Code Online (Sandbox Code Playgroud)

在发布版本的情况下,这将从MSIL中排除.

将ConditionalAttribute应用于方法指示编译器不应将对该方法的调用编译为Microsoft中间语言(MSIL),除非定义了与ConditionalAttribute关联的条件编译符号.将ConditionalAttribute应用于属性表示除非定义了条件编译符号,否则不应将该属性发送到元数据

  • @Lieven Yup,就是这样.刚用ildasm验证 - 没有电话,没有方法代码.确实令人印象深刻 (2认同)