【问题标题】:C# - Why is my wrapper function for error handling not catching exceptions?C# - 为什么我的错误处理包装函数没有捕获异常?
【发布时间】:2020-08-18 06:02:33
【问题描述】:

我正在使用以下一般包装功能:

public static class ErrorHandling
{
    public static void TryCatchErrors<TLogger>(ILogger<TLogger> logger, Action action, string? customMsg = null) => TryCatchErrors<TLogger, object>(logger, () => { action.Invoke(); return 0; }, customMsg);
    public static TOut TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<TOut> action, string? customMsg = null)
    {
        try 
        {
            if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
            if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
            return action.Invoke(); 
        }
        catch (Exception e)
        {
            logger.LogError(e, customMsg ?? e.Message);
        }
    }
}

当我执行以下我的预期用途示例时,我的包装函数无法捕获错误:

    public static async Task DeleteRecords<TLog>(ILogger<TLog> _logger) =>
        await ErrorHandling.TryCatchErrors(_logger, async () =>
        {
            // Other functionality that might throw an unexpected error etc.

            throw new Exception();
        });

虽然我在这里遗漏一些愚蠢的东西的可能性绝对是真实的,但我的印象是,这与一些我不知道并且一直在努力弄清楚自己的较低级别的问题或担忧有关。

提前致谢!

【问题讨论】:

  • 我认为第一个方法不会编译,你正在捕捉异常,但你必须返回一些东西。
  • 为什么你会在那里捕捉到异常,即使你无法解决它。 (例如返回任何有用的东西)当你能够解决它们时捕获异常。

标签: c# .net lambda error-handling wrapper


【解决方案1】:

那是因为你直接返回参数Func&lt;TOut&gt; action返回的任务。这意味着任务可能不会在 TryCatchErrors 中的 try/catch 内执行。目前它只能通过将任务传递给它的调用者来充当代理。

使其异步并在那里等待。通过使其异步并在方法中等待它,您正在使其成为状态机的一部分。所以 try/catch 也将成为其中的一部分。

public async static TOut TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<TOut> action, string? customMsg = null)
{
    try 
    {
        if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
        if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
        await action.Invoke(); 
    }
    catch (Exception e)
    {
        logger.LogError(e, customMsg ?? e.Message);
    }
}

我没有测试它,但我认为你应该将方法签名更改为:

public async static Task<TOut> TryCatchErrors<TLogger, TOut>(ILogger<TLogger> logger, Func<Task<TOut>> action, string? customMsg = null)
{
    try 
    {
        if (logger == null) { throw new ArgumentNullException($"Got null for logger", $"Expected type ILogger<{typeof(TLogger).AssemblyQualifiedName}>!"); }
        if (action == null) { throw new ArgumentNullException($"Got null for action", $"Expected type Func<{typeof(TOut).AssemblyQualifiedName}>!"); }
        await action.Invoke(); 
    }
    catch (Exception e)
    {
        logger.LogError(e, customMsg ?? e.Message);
    }
}

否则你可能不被允许等待它。

【讨论】:

  • 可能将新的异步签名重命名为 TryCatchErrorsAsync,以遵循 .NET 习惯用法。
  • 我很好奇他们何时放弃了异步后缀。它使代码混乱。
猜你喜欢
  • 2018-10-15
  • 2010-11-25
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 2010-11-16
  • 2012-01-22
相关资源
最近更新 更多