我想向我的 C# 应用程序添加日志记录或跟踪,但如果日志详细级别设置得太低以致于不会记录消息,我不希望记录格式化字符串或计算值的开销。
在 C++ 中,您可以使用预处理器定义宏来阻止代码被执行,如下所示:
#define VLOG(level,expr) if (level >= g_log.verbosity) { g_log.output << expr; }
像这样使用:
VLOG(5,"Expensive function call returns " << ExpensiveFunctionCall());
在 C# 中如何做到这一点?
我已阅读解释跟踪和调试功能的 Microsoft 文档here,并且他们声称使用 #undef DEBUG 和 #undef TRACE 会从生成的可执行文件中删除所有跟踪和调试代码,但它真的会删除整个调用吗?意思是,如果我写
System.Diagnostics.Trace.WriteLineIf(g_log.verbosity>=5,ExpensiveFunctionCall());
如果我取消定义 TRACE,它不会调用我昂贵的函数?或者确实拨打了电话,then决定它不会追踪任何东西?
不管怎样,即使它确实删除了它,这也比 C++ 宏要差,因为我不能让那个丑陋的大调用看起来像我在 C++ 中的简单 VLOG() 调用,并且仍然避免评估参数,可以吗?我也无法像在 C++ 中那样通过在运行时定义较低的详细程度来避免开销,对吧?
要回答您的问题之一,如果 Trace.WriteLine 被编译出来,则必须评估才能调用 Trace.WriteLine (或其兄弟/表兄弟)的所有方法调用都不会被调用。因此,请继续将昂贵的方法调用直接作为 Trace 调用的参数放入,如果您没有定义 TRACE 符号,它将在编译时删除。
现在,关于有关在运行时更改详细程度的其他问题。这里的技巧是 Trace.WriteLine 和类似的方法采用“params object[] args”作为其字符串格式化参数。仅当实际发出字符串时(当详细程度设置得足够高时),该方法才会在这些对象上调用 ToString 以从中获取字符串。因此,我经常玩的一个技巧是将对象而不是完全组装的字符串传递给这些方法,并将字符串创建保留在我传入的对象的 ToString 中。这样,仅在实际发生日志记录时才支付运行时性能税,它使您可以自由地更改详细程度,而无需重新编译您的应用程序。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)