大家好。我一直在阅读苹果关于何时/何地/如何使用 NSError 与 @try/@catch/@finally 的建议。本质上,我的印象是苹果认为最好避免使用异常处理语言结构,除非作为在意外错误情况下停止程序执行的机制(也许有人可以举一个这种情况的例子?)
我来自 Java,当人们想要处理错误时,异常是一种可行的方法。诚然,我仍然停留在 Java 思想空间中,但我正在慢慢掌握 NSError 提供的所有内容。
我困扰的一件事是发生错误时清理内存的任务。在许多情况下(例如,使用 C、C++ 库、CoreFoundation 等),在因错误而中断函数之前,需要执行大量内存清理工作。
这是我编造的一个例子,它准确地反映了我遇到的情况。使用一些虚构的数据结构,该函数打开一个文件句柄并创建一个“MyFileRefInfo”对象,其中包含有关如何处理该文件的信息。在关闭文件句柄并释放结构体的内存之前,已经对文件完成了一些操作。使用苹果的建议我有这个方法:
- (BOOL)doSomeThingsWithFile:(NSURL *)filePath error:(NSError **)error
{
MyFileReference inFile; // Lets say this is a CF struct that opens a file reference
MyFileRefInfo *fileInfo = new MyFileRefInfo(...some init parameters...);
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:99 userInfo:nil];
delete fileInfo;
return NO;
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:100 userInfo:nil];
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
return NO;
}
err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:101 userInfo:nil];
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
return NO;
}
CloseFileHandle(inFile);
delete fileInfo;
return YES;
}
现在..我的Java逻辑告诉我,最好将其设置为try/catch/finally结构,并将所有关闭文件句柄和释放内存的调用放在finally块中。
就像这样..
...
@try
{
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
... throw some exception complete with error code and description ...
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
... throw some exception ...
}
... etc ...
}
@catch(MyException *ex)
{
*error = [NSError errorWithDomain:@"myDomain" code:[ex errorCode] userInfo:nil];
return NO;
}
@finally
{
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
}
return YES;
我是否疯狂地认为这是一个更优雅的解决方案,冗余代码更少?
我错过了什么?