是否有一种使用DebugFormat()的方法,其中args构造起来很昂贵?

E-R*_*Riz 4 c# log4net

我是log4net和log4j 用于记录消息的"格式"API的忠实粉丝,如果没有启用必要的日志级别,这可以避免在参数上调用ToString()的成本.

但是有时候我使用的一个或多个参数不是一个简单的对象,它需要以某种方式构造.例如,像这样:

logger.DebugFormat("Item {0} not found in {1}",
        itemID,
        string.Join(",", items.Select(i => <you get the idea>))
       );
Run Code Online (Sandbox Code Playgroud)

是否有一种封装第二个参数(Join表达式)的技术,除非DebugFormat决定它应该是(就像它对第一个参数的ToString所做的那样),否则它不会被执行?

感觉就像一个lambda或func或者其他东西应该可以在这里提供帮助,但我对C#还是比较新的,我不能完全把手指放在它上面.

Evk*_*Evk 6

您可以创建扩展方法或包装类,但要获得令人满意的语法并不容易,因为您需要itemID明确声明某些参数(在您的示例中),并且只有在必要时才能解析一些参数.但你不能传递匿名功能object.相反,我会使用另一种不需要扩展方法或包装器的解决方案.像这样创建类:

public sealed class Delayed {
    private readonly Lazy<object> _lazy;
    public Delayed(Func<object> func) {
        _lazy = new Lazy<object>(func, false);
    }

    public override string ToString() {
        var result = _lazy.Value;
        return result != null ? result.ToString() : "";
    }
}
Run Code Online (Sandbox Code Playgroud)

这接受在构造函数中返回对象的函数,并且在调用之前不会调用此函数ToString(),正如您所知,只有在必要时才会调用log4net(如果启用了此类调试级别).然后像这样使用:

logger.DebugFormat("Item {0} not found in {1}",
    itemID,
    new Delayed(() => string.Join(",", items.Select(i => <you get the idea>)))
   );
Run Code Online (Sandbox Code Playgroud)