You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于.NET 10中CA1873警告的日志优化实现思路疑问

.NET 10中CA1873警告的日志优化实现思路疑问

兄弟,我太懂你这种烦躁了——本来写日志就是图个轻量方便,结果突然冒出来CA1873警告,还要手动给每处日志套个if (_logger.IsEnabled(...))的判断,想想都头大。

先给你掰扯清楚官方为啥没搞你说的那种Lazy重载,再给你俩实际可用的解决方案,你自己选:

为啥官方没做Lazy参数的日志重载?

其实官方不是没想到,而是他们更推荐性能更优、规范度更高的结构化日志方案,而不是通过新增API来“妥协”。主要有两个原因:

  1. 已有更高效的替代方案:官方主推的LoggerMessage.Define模式,本身就自带延迟计算+编译时优化,比你写的运行时Func委托性能好得多。它会在编译阶段生成强类型的日志委托,自动帮你做IsEnabled判断,完全不需要手动加if。比如:

    // 提前定义好日志模板(一般放类的静态字段里)
    private static readonly Action<ILogger, int, Exception?> _logMessageCount =
        LoggerMessage.Define<int>(
            LogLevel.Information, 
            new EventId(1, "MessageCount"), 
            "My message:{MessageCount}.");
    
    // 调用的时候直接传参数就行,自动处理判断
    _logMessageCount(_logger, messages.Count, null);
    

    这种方式不仅没有额外的运行时开销,还能保证日志的结构化一致性,是官方最推荐的生产级方案。

  2. API复杂度控制:如果给每个日志级别都加一套Lazy重载,会让ILogger的API变得异常臃肿,而且不同开发者可能会混用普通Log和LazyLog,反而增加代码的维护成本。官方更倾向于引导开发者用标准方案,而不是提供过多的“捷径”API。

不想加if判断?给你两个可行的路子

路子一:自己封装Lazy扩展(适合快速改造现有代码)

你想的那个扩展方案完全可行!甚至可以优化得更顺手一点,比如支持可变参数的Func<object>,不用手动创建数组:

public static class LoggerLazyExtensions
{
    public static void LogInformationLazy(this ILogger logger, string message, params Func<object>[] parameterFactories)
    {
        if (!logger.IsEnabled(LogLevel.Information)) return;
        var parameters = parameterFactories.Select(f => f()).ToArray();
        logger.LogInformation(message, parameters);
    }

    // 同理可以给其他日志级别(Debug/Warning/Error等)都加上对应的扩展
    public static void LogDebugLazy(this ILogger logger, string message, params Func<object>[] parameterFactories)
    {
        if (!logger.IsEnabled(LogLevel.Debug)) return;
        var parameters = parameterFactories.Select(f => f()).ToArray();
        logger.LogDebug(message, parameters);
    }
}

// 调用的时候直接写:
_logger.LogInformationLazy("My message:{MessageCount}.", () => messages.Count);

这个方案几乎不需要改现有日志的写法,只是把LogInformation换成LogInformationLazy,完美解决CA1873警告,还不用加if判断。

路子二:改用LoggerMessage(适合新项目或重构项目)

如果是新项目或者有时间重构老代码,强烈建议用官方的LoggerMessage模式,性能拉满还规范。除了上面的例子,还可以用LoggerMessage.DefineScope处理日志上下文,功能更完整。

最后总结

  • 官方没加Lazy重载是因为有更高效的标准方案,不是没想到
  • 你自己封装Lazy扩展完全没问题,是快速解决问题的好办法
  • 追求性能和规范的话,选LoggerMessage准没错

说白了就是看你项目的情况:如果是老项目不想大改,自己封装扩展;如果是新项目或者要优化性能,就上LoggerMessage。怎么舒服怎么来就行!

火山引擎 最新活动