【问题标题】:position of the try catch statementtry catch 语句的位置
【发布时间】:2014-03-02 09:58:54
【问题描述】:

我有一些目前看起来有点像这样的代码:

public void MainFunction() 
{
   try
   {
      SomeProblemFunction();
   }
   catch
   {
      AllFineFunction();
   }
}

private void SomeProblemFunction() { ... }
private void AllFineFunction() { ... }

如您所见,我目前将对 SomeProblemFunction 的调用包装在 try 语句周围,因为该函数可能会失败(它依赖于外部 Web 服务调用)。

我的问题是:try 语句应该是 a) 问题函数之外(就像我现在拥有的那样)还是 b) 问题函数内部?

谢谢。

【问题讨论】:

标签: c#


【解决方案1】:

通常您希望允许异常传播到您的应用程序边界。除了例外,您只想做几件事之一:

  • 包起来
  • 替换它
  • 让它传播

更新

从您的问题来看,您似乎正在为您的 Web 服务调用寻找容错解决方案。这是一个比简单的“我将 try-catch 放在哪里?”更复杂的问题。您仍然会将异常处理放在应用程序边界,但您将在那里实施容错策略。这需要考虑很多因素,包括异步调用您的 Web 服务、重试尝试次数等。我建议您搜索 Web 服务容错。

【讨论】:

  • 重试逻辑呢?当尝试操作但失败,而不是在应用程序中备份时,可能会发生这种情况。建议太窄了,IMO。
  • @PeterRitchie,我已经更新了我的答案以包含您的疑虑。
【解决方案2】:

你所拥有的是正确的;见MSDN example:

public class ThrowTestB
{
    static void Main()
    {
        try
        {
            // TryCast produces an unhandled exception.
            TryCast();
        }
        catch (Exception ex)
        {
            // Catch the exception that is unhandled in TryCast.
            Console.WriteLine
                ("Catching the {0} exception triggers the finally block.",
                ex.GetType());

            // Restore the original unhandled exception. You might not 
            // know what exception to expect, or how to handle it, so pass  
            // it on. 
            throw;
        }
    }

    public static void TryCast()
    {
        int i = 123;
        string s = "Some string";
        object obj = s;

        try
        {
            // Invalid conversion; obj contains a string, not a numeric type.
            i = (int)obj;

            // The following statement is not run.
            Console.WriteLine("WriteLine at the end of the try block.");
        }
        finally
        {
            // Report that the finally block is run, and show that the value of 
            // i has not been changed.
            Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
        }
    }
    // Output: 
    // In the finally block in TryCast, i = 123. 

    // Catching the System.InvalidCastException exception triggers the finally block. 

    // Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
  • 我同意@RaulRene。我继续为你编辑了它,所以它不会被删除。
【解决方案3】:

根据经验,我尝试构建代码,将 try 捕获集中到问题可能发生的确切位置。

也就是说你的两个解决方案都是正确的。

如果是我的代码,我会这样做

public void MainFunction() 
{
   try
   {
      SomeProblemFunction();
   }
   catch(Exception e)
   {
      Messagebox.Show(e.Message);
   }
}

private void SomeProblemFunction() {
    try{
        web call
    }
    catch{
         throw a specific exception related to this spot
    }
}
private void AllFineFunction() { ... }

使用此方法,您可以轻松创建处理大量非常准确的异常的应用程序

【讨论】:

  • 你会如何决定在 SomeProblemFunction 中抛出 what 异常?您没有发现特定异常?
  • 我将其留空,因为您可以创建自己的内容或选择捕获任何您想要的内容。我只是在画一幅画
  • OP已经很困惑了,很明显他需要一些明确的答案而不是更多的混乱。
  • @PeterRitchie 好吧,如果你是正确的,幸运的是,OP 有许多其他解决方案可以采取。他没有义务接受我的。感谢您的洞察力
【解决方案4】:

我认为这是一个很好的问题。我会尝试回答。


如果您想在SomeProblemFunction 中恢复,那么将try...catch 移动到该方法中是非常有意义的。但是,如果您很自在地说如果 SomeProblemFunction 中出现任何故障,那么整个事情都是失败的,那么请保持现在的状态并恢复(或从)MainFunction


感谢下面的评论,我增加了一些清晰度。根据SomeProblemFunction 中引发的特定异常,您可能无法在该方法中恢复。如果您有可恢复和不可恢复的混合,那么在这两个地方都有try...catch 是谨慎的。

最重要的是,您永远不会捕捉到一个异常,如果在做完你的事情后不抛出它就无法恢复。添加大范围的捕获 (catch (Exception)) 以避免您的应用程序在开发过程中崩溃是很诱人的,但这绝不值得。如果这些东西进入了您的生产代码,那么您已经引入了解决问题和调试的噩梦。

【讨论】:

  • “想要”和“可以”是两个不同的东西。
  • 确实如此。我会补充一点,谢谢。
【解决方案5】:

在我看来,对此没有直接的答案。 try catch 用于处理可能发生的异常。如果您的异常处理代码在 main 函数中,那么您应该在 main 函数中使用 try catch。如果您的异常处理代码在问题函数中,那么您应该将其添加到问题函数中。

我的偏好是把它放在两个函数中。如果把try catch放在问题函数中,可以抛出异常并在main函数中捕获。对于其他开发人员来说,这总是会在该函数中考虑到异常并且不会错误地处理它。

【讨论】:

    【解决方案6】:

    这取决于此 Web 服务调用失败的严重程度。

    它是否会阻止进一步处理您的代码以运行?如果是这样,请不要在此处尝试/捕获,让它传播到需要知道此 Web 服务调用失败的人。或者,您仍然可以捕获并抛出一个带有一些更有意义的异常类型/详细信息的新异常。

    如果 Web 服务调用不起作用,您是否只是想再次重试该 Web 服务调用?如果是这样,那么您可以在正确的地方尝试;你只需要添加一个循环。

    如果此 Web 服务调用失败,这不是什么大问题吗?例如- 您的其余代码可以正常工作吗? (我发现这并不常见)。如果是这样,请将 try/catch 保留在原处,并将错误记录在某处以便收到警报。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-19
      相关资源
      最近更新 更多