一般来说goto很糟糕(我们都知道为什么)在不必复制代码的情况下,对错误实现简单清理(如下例所示)的更好方法。在我看来,下面的代码很好,我只是好奇别人会做什么:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]
int returnCode = 0;
// ... Other code
// WRITE: To file
if([dataStore writeToFile:savePathData atomically:YES] == NO) {
NSLog(@"writeToFile ... Error");
returnCode = 1;
goto cleanUpCode;
}
// ... Other code
// Clean up
cleanUpCode:
[archiver release];
[newPlanet release];
[pool drain];
return(returnCode);
}
总的来说,我同意@try,@ catch,@ finally不仅仅是肯定的方式,但我确实有两个小问题。
(1)三个@try,@ catch,@ finally块必须全部在一起,你没有灵活性在@catch和@finally之间放置你可能想要绕过的代码。
(2)Apple的Obj-C 2.0文档声明如下:“重要:在Objective-C中,异常是资源密集型的。您不应该使用异常来进行一般流量控制,或者只是表示错误(例如文件无法访问)“。
多得多的
加里
答案 0 :(得分:5)
这是C代码中常见的习惯用法,在没有更全面的创建/破坏语义的语言的情况下,我认为它没有任何问题。
Goto在一般意义上被认为是有害的;它可以使程序执行难以遵循。这里,它的范围非常有限,流量是单向的。从某种意义上讲,它也可以帮助您本地化清理代码,这是一件好事。
答案 1 :(得分:4)
好吧,首先我会尝试将它重构为更多的方法,也许那么代码就不会那么难以辨认?
此外,您始终可以使用自动释放的对象,因此最后只需要[pool drain]
。这可以使用@try
/ @finally
来完成,这样您就可以return 1
代替returnCode = 1
。
E.g。看一下Exception Handling and Memory Management文档(我知道你的问题不是关于异常,但基本上都是一样的) - 他们推荐这样的东西:
- (void)doSomething {
NSMutableArray *anArray = nil;
array = [[NSMutableArray alloc] initWithCapacity:0];
@try {
[self doSomethingElse:anArray];
}
@finally {
[anArray release];
}
}
就个人而言,这就是我要做的事。
答案 2 :(得分:0)
有很多方法可以做到这一点。这是一对夫妇:
编写与您的主代码相对应的程序,例如: RunApplication。将调用放在“else”分支中。
将它放在try / catch中,在“catch”部分进行错误处理,否则进行正常处理。
代码
e.g. try {
.. check for error (any function/procedure that checks for an error can throw an exception
.. do normal processing (still a good idea to factor this out into a procedure, for clarity
}
catch {
.. handle errors
}
finally
{
.. do cleanup
}
任何时候你认为你需要goto,对于错误情况,你可能会发现try / catch和exception更好。
在没有try / catch的语言中,只需使用重构。
答案 3 :(得分:-1)
当你描述的东西看起来像一个小命令行程序时,我不会担心它。因为当你的程序结束时,程序分配的所有内存都将返回给系统(它将不复存在)。但是,如果你有一个更大的程序,分配了很多并运行了一段时间,你可能会更正确地考虑清理,因为它可以帮助追踪内存泄漏,这可能会影响运行较长时间的程序。在这种情况下,我还建议使用一些宏。
#define THROW( _name ) goto label_ ## _name
#define CATCH( _name ) label_ ## _name:
:
:
if([dataStore writeToFile:savePathData atomically:YES] == NO) {
NSLog(@"writeToFile ... Error");
returnCode = 1;
THROW( cleanUpCode );
}
:
:
CATCH( cleanUpCode )
[archiver release];
[newPlanet release];
[pool drain];