代码之家  ›  专栏  ›  技术社区  ›  Miyagi Coder

C中的异常处理:多个尝试/捕获与一个尝试/捕获

  •  5
  • Miyagi Coder  · 技术社区  · 16 年前

    有多个是好的做法吗 try{} catch{} 每个方法的声明?

    12 回复  |  直到 16 年前
        1
  •  14
  •   Brian Rasmussen    16 年前

    在我看来,最好的做法是让每个方法只处理一个任务。因此,在一个方法中很少需要多个try/catch块。不过,我看不出有什么问题。

    正如丽莎指出的,你应该抓住具体的例外 只有 捕获方法实际可以处理的异常。

        2
  •  6
  •   l15a    16 年前

    最好让一个带有多个catch的try/catch以不同的方式处理每种类型的异常。

        3
  •  6
  •   Bullines    16 年前

    如果您知道可以预先发生的异常的类型,那么您可以尝试一次并捕获每个异常,如果您想以不同的方式处理它们的话。例如:

    try
    {
        // a bunch of risky code
    }
    catch (SpecificException1 ex1)
    {
         // handle Specific Exception 1
    }
    catch (SpecificException2 ex2)
    {
         // handle Specific Exception 2
    }
    catch (SpecificException3 ex3)
    {
         // handle Specific Exception 3
    }
    catch (Exception ex)
    {
         // handle an exception that isn't specific
    }
    
        4
  •  6
  •   Sara Chipps    16 年前

    在我看来,如果你知道可能发生在你手前的异常情况,你就不应该用Try…Catch来获取错误。

    不要例外编程….所以我不认为倍数是个好主意。

        5
  •  4
  •   Marc Gravell    16 年前

    一般来说,我有很多 finally catch . 通常,没有太多 具体的 你可以做一个例外,所以让它冒泡。但是 最后 确保你能把东西关得干干净净等。

        6
  •  4
  •   Rinat Abdullin    16 年前

    对于复杂的生产级场景,拥有多个try-catch语句是一种可怕的实践,而在业务逻辑中拥有这些语句是非常不灵活的实践。

    Windows云计算团队(他们的代码必须高效可靠)似乎坚持 Exception Handling Action Policies 相反。

    此代码是更好的替换:

    // perform action within the policy
    policy.Do(() => repository.AddMessages(someMessages));
    

    虽然旧代码块看起来像:

    try
    {
      repository.AddMessages(someMessages);
    }
    catch (Exception1 ex)
    {
      // dosomething...
    }
    catch (Exception2 ex)
    {
      // second handler
    }
    catch (Exception3 ex)
    {
      // third handler
    }
    

    或者(这是在硬编码操作策略中提供可配置异常处理程序的Microsoft企业库方法):

    try
    {
      repository.AddMessages(someMessages);
    }
    catch (Exception ex)
    {
      bool rethrow = ExceptionPolicy
        .HandleException(ex, "Global Policy");
      if (rethrow)
      {
        throw;
      }
    }
    

    另外,如果你有 action policy ,您可以告诉它(配置)对某些类型的异常进行日志记录、睡眠、重试,而不是简单地失败或执行其他硬编码操作。

        7
  •  2
  •   BenAlabaster    16 年前

    作为经验法则,每个方法都应该处理一个任务——这个最佳实践源自一个测试驱动的环境,这使得生成测试更加容易。为“上帝”程序编写测试计划本身就比较困难。

    因此,最好只在可能失败的项目周围使用try catch,并且只在通常情况下捕获异常以进行有用的处理时使用。

    不要使用一次catch来包装方法的整个内容,从而消除对体面编码实践的责任。

    处理异常是一项昂贵的操作-在必要时捕获异常并编写代码以防止在其他地方发生异常。在某些情况下,防止异常本身并不简单,但可以使用try/catch捕获并有效地使用异常,例如检查文件操作的排他性。

    当你使用“尝试/捕获”时,要有意识地做出决定,不要仅仅因为你可以,而把它扔进去,那是懒惰的。问问自己“我需要它吗?”或者“我能用一种更便宜和/或更结构化的方法做到这一点吗?”.

        8
  •  1
  •   Kekoa    16 年前

    我想说那要视情况而定。在我看来,到处都是这种尝试性的捕猎有点马虎。我试着合并到一个有很多捕获物的试验区。有时这不起作用,你可能需要把它们分开,但为了保持内容的可读性,至少我喜欢这样。

    当然,如果您的方法太长,您可以提取方法来分发您的尝试捕获。

        9
  •  1
  •   Andy Webb    16 年前

    视情况而定。异常处理的目的就是在运行时异常发生时处理它们。

    我通常有一个catch all try/catch,然后在我知道有可能引发异常(类型转换等)的代码区域周围放置try catch块。

        10
  •  1
  •   Robert Rossney    16 年前

    使用多个try/catch块的优点是它明显地将您尝试的操作与预期的异常配对。一般来说,如果引发异常的条件不可恢复,则不会捕获异常(除非您正在执行某些操作,例如记录特定的异常以进行诊断)。像这样的代码:

    try
    {
       Operation1();
    }
    catch (MySpecificException1)
    {
       RecoverFromExpectedException1();
    }
    try
    {
      Operation2();
    }
    catch (MySpecificException2)
    {
       RecoverFromExpectedException2();
    }
    

    可能有点冗长,但这是使用异常进行流控制的结果。重要的是,通过查看此代码,您可以知道第一个操作可能引发特定的异常,并且您的代码知道如何从该异常中恢复并继续执行第二个操作。Try/Catch块没有做任何其他操作 但是 那。

        11
  •  1
  •   Scott Langham    16 年前

    每个方法甚至有一个try/catch都是不好的做法。

    异常完全是为了减少错误处理代码的编写,而不是像其他答案所建议的那样。

    在异常之前,您必须通过测试返回值来检查每一行代码是否成功,如果有什么问题,就必须用返回值将其传递回调用堆栈。这意味着每种方法都必须测试并返回。发明了异常,这样方法就不必到处都需要这些检查,而且您可以拥有一系列可读的代码行,因为它们不会被错误处理所掩盖。

    所以…建议是,您应该拥有尽可能少的尝试/捕获,这意味着大多数方法都不需要任何尝试/捕获。

    但是,这里有一些地方应该使用它们:

    • 当操作失败(写入日志文件或向用户显示错误消息)时,仅当您知道程序可以继续并且由于某个操作失败而现在未处于损坏状态时,才执行此操作。操作必须彼此隔离。
    • 在您的主方法中,记录在程序因异常而终止之前未在其他地方处理的任何异常。
    • 在可以采取操作的地方,例如重试操作或回退到较低的操作模式。
    • 如果有一个糟糕的API,它不会让您测试需要处理的条件。例如,如果您想打开一个文件,而API没有提供doesfileexist(),则可以首先调用。

    我现在想不出其他地方…那是因为尝试/捕获应该是少而远的!

    每当抛出异常时,我总是将调试器设置为中断。它很少中断,因为异常是例外。

        12
  •  1
  •   Bent André Solheim    16 年前

    我发现合并许多行代码,每行代码都可以将自己的异常抛出到一个带有许多捕获的try块中,这使得代码很难读取。从代码来看,不清楚哪一行代码引发了什么异常。在我看来,try捕获应该包含尽可能少的代码;只有能够抛出给定异常的代码。如果您正在编写的方法包含多个try捕获,则应将每个捕获提取到自己的方法中。

    如果在方法中有多个方法调用引发同一异常,则这一点变得更重要。然后它们真的应该在单独的try捕获中,因为当捕获异常时,您通常希望用一条相关的错误消息将其包装在一个适合当前抽象的新异常中。如果两个语句都在同一个try catch中,则会失去为不同的错误提供不同错误消息的机会。

    Object operationResult;
    try {
      operationResult = remoteService.performRemoteOperation();
    } catch (RemoteException ex) {
      throw new BusinessException("An error occured when getting ...", ex);
    }
    
    // use operation result