Language agnostic 向异常添加额外信息

Language agnostic 向异常添加额外信息,language-agnostic,exception-handling,Language Agnostic,Exception Handling,假设我有一个从csv文件中读取客户的方法 读取文件时发生异常(例如IOException或FormatException)。在大多数情况下,该方法无法处理错误,但可以添加额外的信息,如文件名、行号等 该方法的类具有用于记录/显示错误的IProgressAndErrorReporter依赖项 我如何向调用者报告发生了错误,但已经处理好了? 目前我是这样做的: class CustomerReader { private readonly IProgressAndErrorReporter

假设我有一个从csv文件中读取客户的方法

读取文件时发生异常(例如IOException或FormatException)。在大多数情况下,该方法无法处理错误,但可以添加额外的信息,如文件名、行号等

该方法的类具有用于记录/显示错误的IProgressAndErrorReporter依赖项

我如何向调用者报告发生了错误,但已经处理好了?

目前我是这样做的:

class CustomerReader
{
    private readonly IProgressAndErrorReporter mProgressAndErrorReporter;

    public bool TryReadCustomers() {
        try {
            ...
            return true;
        }
        catch (IOException err) {
            mProgressAndErrorReporter.ReportError(err, "Can't read file {0} bla bla");
            return false;
         }
    }
 }
(我只捕获“预期”异常,即非无效操作等)
我可以很好地工作,但在数据处理应用程序类型中,我通常使用上面的级别:

public bool TryProcessData() {
    if (!customerReader.TryReadCustomers())
        return false;

    var orders = webOrderReader.ReadNewOrders());
    if (orders == null)
        return false;

    if (!orderCreator.TryCreateNewOrder(order))
    ...

}
对我来说,这感觉就像回到了例外之前的时代


我是否应该抛出某种类型的“AlreadyHandledException”,而在顶层使用一个空的catch子句?

不要回到过去,而是用一个更高级别的异常来包装它。在这种情况下,您应该为实例定义ReadCustomerDataException和ReadNewOrderException。这样做的另一个好处是创建可读性很强的代码。创建一个新的异常并不难,如果您的语言有内部类,那么您可以创建一个公共内部类

最后,如果您应该返回布尔值,这取决于用例,但我建议您在更高级别的方法中捕获自定义(选中)异常,该方法实际上需要布尔值,而不是之前的值

如果您的方法在正常情况下注定会失败,那么不要抛出异常,而是返回一个(自定义)结果类。这将确保您和您的同事不必确保调试器在正常操作时停止在代码中。最后,如果存在许多不应停止应用程序的异常,则可能希望将结果类传递给侦听器,而不是在方法末尾返回它


PS仅在您确定信息存在时才包括额外信息(否则您将在异常处理中生成异常)-不太好(错误,找不到错误表是我的最爱)。

感谢您回答这个老问题。我不明白为什么我应该创建更多的自定义异常。任何可以做的事情(回滚、记录任何事情)都已经发生了。我只想以一种干净的方式退出顶层函数?创建日志,这样不会改变应用程序的内部工作。在调试问题或其他维护期间,重要的是要有语义正确的异常。在您的示例中,您说异常已被处理,但这只是关于日志记录和资源处理的情况:应用程序仍处于异常状态(您跳过了重要部分的执行)。这应该用表示该状态的异常来表示。