处理异常的更简洁方法是什么?

时间:2013-07-21 04:42:08

标签: c# exception-handling

请参阅此代码:

 try
    {
        int val = GenericLibrary.ConvertToInt(userInput);
        return "Valid number";
    }
    catch (Exception)
    {
        return "Invalid number";
    }

我编写了一个控制台应用程序,其中包含许多尝试捕获块。我希望以更干净的方式处理异常并遵循DRY原则。

控制台应用程序c#中处理错误的最佳方法是什么?

我可以使用Func还是Action?

我可以使用面向方面的编程吗?

3 个答案:

答案 0 :(得分:4)

我想澄清一下,清洁 - 如果您只想在一个地方编写错误处理代码,那么您可以使用AOP(例如PostSharp)。但是通过AOP实现错误处理程序,然后它们将在您的exe中随处编译。

另外请记住,这会违反异常处理程序应该异常使用的规则。

我不确定为什么要在Try-Catch中将string强制转换包装到int

您可以通过设置全局异常处理程序Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException来在一个位置处理意外异常。请记住处理您期望的所有异常,例如要转换为int的字符串。

您可以为此演员表使用Func,但使用简单的方法会更容易:Integer.TryParse

答案 1 :(得分:3)

什么是干净取决于很多因素。通过PostSharp或其他AOP处理程序的一般异常处理程序,例如来自企业库的 Exception Handling Application 块甚至可以让您配置策略。虽然一个好主意,但是在策略注入应用程序块到位之前它从未获得太大的吸引力,这也是一个AOP框架,它允许您以可配置的方式集中处理异常。

然而,实际上异常处理仍然很难。第一条规则应该是永远不要隐藏异常。您当然可以捕获它们,但是当您不让它们进一步传播时,您应该始终记录它们。如果您的GenericLibrary使用一些配置文件来决定应该处理整数的哪个区域设置并且找不到它的配置文件怎么办?您会遇到重复错误,但在调试之前您永远不会找到根本原因,因为您丢弃了异常对象并返回了一个字符串。

同样糟糕的“处理”策略是

catch(Exception ex)
{
   Log("Error has occured: {0}", ex.Message);
}

这将为您提供错误消息,但您将丢失完整的调用堆栈和任何内部异常。如果您收到一些像TargetInvocationException这样只包含一般错误消息的通用包装器异常,那么这一点尤其糟糕。

正确的处理策略在很大程度上取决于您的具体情况。如果你的控制台应用程序是一个没有交付给客户的小应用程序,那么在第一遍中删除所有catch处理程序并在main方法中全局处理它们通常是最简单的。然后,当您有最常见的非致命错误的经验时,您可以重新添加必要的捕获处理程序以重新获得稳健性。现在你继续研究非致命错误,但你保留了致命错误的失败策略。

此处的任何先前答案仅向您提供使用此策略或该策略的建议,但您需要根据具体情况决定哪些异常对您的应用程序不重要。当你抓住所有东西时,你不会发现为什么你的应用程序由于内部捕获的错误而什么也没做。如果您没有任何处理,您的应用程序将终止每个非致命错误(例如,如果无法在您的应用程序中解析该值,则可以返回0)。

对于小型控制台应用,我会

  • 删除所有捕获块
  • 即使在Main方法
  • 中也是如此

这样,您可以在应用程序事件日志中自动记录.NET Framework,如果您的应用程序崩溃,则无需额外工作。如果您的控制台应用程序已执作为预定的作业打印输出到控制台将无济于事。这是处理异常的最简洁方法:根本不处理并让您的应用程序崩溃,以便您可以找出应用程序事件日志中出现的问题。

如果除了可执行文件之外还部署用于发布版本的pdbs,您还可以获得行号和文件信息,这使得在大多数情况下很容易发现错误。

如果您的应用程序是关键任务或交付给客户,则可能发生在您身上 需要使用一些日志框架来记录一些私有日志文件。控制台应用程序和Windows应用程序之间的区别仅是PE标头中的标志。 Windows应用程序将从当前启动的控制台分离,而控制台应用程序将保持与其连接。这是唯一的区别。您还可以在控制台应用程序中创建WPF应用程序,但只要它运行可能不是您想要的东西,它就会阻止您的控制台。

但是如果你切换到Windows应用程序,你可以分配一个新的控制台,使Console.WriteLine再次发挥作用,你可以继续使用printf调试,这可能是最常用的调试方法,虽然是一个非常老式的调试方法。

通常,您会在应用程序中添加一个跟踪库,以跟踪默认情况下关闭的应用程序流。还应该进行记录,始终只记录错误。如果错误记录不够,通过这种方法,您可以在客户机器上遇到更多麻烦。

答案 2 :(得分:0)

如果你想要使用Func,请看: 你可以用这个

public static class SafeExecutor
{
    public static T Execute<T>(Func<T> operation)
    {
        try
        {
            return operation();
        }
        catch (Exception ex)
        {
            // Log Exception
        }
        return default(T);
    }
}

var data = SafeExecutor.Execute<string>(() =>
{
    // do something
    return "result";
});