【问题标题】:In what circumstances is @finally non-redundant in Cocoa's try/catch/finally Exception Handling?@finally 在 Cocoa 的 try/catch/finally 异常处理中什么情况下是非冗余的?
【发布时间】:2010-10-18 23:58:58
【问题描述】:

考虑以下 Cocoa/Obj-C 代码 sn-ps:

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
@finally {
    [obj cleanUp];
}

MyClass *obj;
@try {
    [obj doSomething];
}
@catch (NSException * e) {
    NSLog(@"Exception occurred: %@", [e description]);
}
[obj cleanUp];

在什么情况下第一个 sn-p 会导致[obj cleanUp] 被调用,而第二个不会导致[obj cleanUp] 被调用?也就是说,在什么情况下@finally在使用Cocoa异常处理时是非冗余的?

【问题讨论】:

    标签: objective-c cocoa exception exception-handling try-catch


    【解决方案1】:

    还值得注意的是,@finally 块中的代码将在控制退出@try 块时运行出于任何原因,即使是通过returngoto。例如:

    @try {
        doStuff();
        if(bail){
            return;
        }
        doMoreStuff();
    }
    @finally {
        [obj cleanUp];
    }
    [obj announceSuccess];
    

    即使bail 为真,[obj cleanUp] 也会执行,但[obj announceSuccess] 不会。

    【讨论】:

      【解决方案2】:

      一个较低级别的问题,你为什么要这样做?

      try/catch/finally 方法在 Java 中被广泛使用,但在 Objective-C 中几乎没有使用过,并且不是首选方法 - 您根本不需要它,因为库不会像 Java 库调用那样抛出异常,如果您正在编写自己的库,则不应期望调用者自然会考虑寻找要捕获的异常。

      最广泛使用和理解的约定是具有错误方法回调的委托,或者可能通知您需要通过多个代码级别传递的更一般的故障。如果有一个像 Cocoa 那样设置的简单通知系统,那么这种方法可能会在 Java 世界中得到更广泛的应用。

      委托方法与在 Java 中声明异常具有相同的文档属性,它们只是不同的方法,但通常最好使用更适合手头语言的方法,除非有非常令人信服的理由不这样做。

      【讨论】:

      • 我目前正在使用 try/catch/finally,因为 OS X 10.5 中的 Apple 脚本桥经常会因抛出异常而失败。如果您使用 Scripting Bridge,就无法避免异常。不过我完全同意,对于大多数 Cocoa/Objective-C 代码,异常并不是处理错误的最佳方式。
      【解决方案3】:

      在这些情况下没有区别,因为异常被吞没了。以下是两个不同的场景:

      [obj cleanUp] 被调用:

      MyClass *obj;
      @try {
          [obj doSomething];
      }
      @catch (NSException * e) {
          @throw;      
      }
      @finally {
          [obj cleanUp]; // called when exception is caught
      }
      

      [obj cleanUp] 未被调用:

      MyClass *obj;
      @try {
          [obj doSomething];
      }
      @catch (NSException * e) {
          @throw;
      }
      [obj cleanUp]; // not called when exception is caught
      

      【讨论】:

        【解决方案4】:

        时间:

        • 您没有捕捉到发生的异常类型
        • 您捕获了异常,但 catch 块中的代码也引发了异常。

        【讨论】:

          【解决方案5】:

          在这种情况下,您正在压缩异常,没有。 @finally 用于在您没有捕获异常或重新抛出异常时进行清理,在任何一种情况下都将最终异常响应留给调用代码。由于 Cocoa 中的异常只应该用于编程错误,因此很少发生,这是完全合理的做法。

          还值得指出一种情况,您不需要使用@finally,即您设置自己的自动释放池。当“父”自动释放池被销毁时,任何尚未清理的内部自动释放池也将被销毁。如果您确实尝试自己清理它,则需要将异常本身从您的自动释放池中提升出来。

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-18
          • 2019-01-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多