我想在我的C#应用程序中添加日志记录或跟踪,但是如果将日志详细级别设置得太低以至于不记录消息,我不希望记录格式化字符串或计算值的开销.
在C++中,您可以使用预处理器来定义将阻止代码执行的宏,如下所示:
#define VLOG(level,expr) if (level >= g_log.verbosity) { g_log.output << expr; }
像这样使用:
VLOG(5,"Expensive function call returns " << ExpensiveFunctionCall());
你是怎么用C#做的?
我读过的微软文档解释了跟踪和调试设施在这里,他们声称,使用和#undef DEBUG和#undef TRACE删除所有从生产的可执行文件跟踪和调试代码,但它真的删除整个通话?意思是,如果我写的话
System.Diagnostics.Trace.WriteLineIf(g_log.verbosity>=5,ExpensiveFunctionCall());
如果我取消定义TRACE,它不会调用我昂贵的功能吗?或者是打电话,然后决定它不会追踪任何东西?
无论如何,即使它确实删除它,这也不如C++宏,因为我无法使那个大丑陋的调用看起来像我在C++中的简单VLOG()调用,仍然可以避免评估参数,是吗?我也不能像在C++中那样在运行时定义详细程度来避免开销,对吧?
要回答您的一个问题,如果编译出Trace.WriteLine,则不会调用必须为了调用Trace.WriteLine(或其兄弟/堂兄弟)而调用的所有方法调用.因此,继续将昂贵的方法调用直接作为Trace调用的参数,如果没有定义TRACE符号,它将在编译时被删除.
现在为您提供有关在运行时更改详细程度的其他问题.这里的技巧是Trace.WriteLine和类似的方法采用'params object [] args'作为字符串格式化参数.只有在实际发出字符串时(当详细程度设置得足够高时),该方法才会对这些对象调用ToString以从中获取字符串.所以我经常玩的一个技巧是将对象而不是完全组装的字符串传递给这些方法,并将字符串创建保留在我传入的对象的ToString中.这样,运行时性能税只在日志实际发生时支付,它让您可以自由地更改详细程度,而无需重新编译您的应用程序.