【发布时间】:2013-09-01 01:39:01
【问题描述】:
今天早上我有这样一个想法,即避免嵌套 try finally 块,如下所示
procedure DoSomething;
var
T1, T2, T3 : TTestObject;
begin
T1 := TTestObject.Create('One');
try
T2 := TTestObject.Create('Two');
try
T3 := TTestObject.Create('Three');
try
//A bunch of code;
finally
T3.Free;
end;
finally
T2.Free;
end;
finally
T1.Free;
end;
end;
利用接口的自动引用计数,我想出了
Type
IDoFinally = interface
procedure DoFree(O : TObject);
end;
TDoFinally = class(TInterfacedObject, IDoFinally)
private
FreeObjectList : TObjectList;
public
procedure DoFree(O : TObject);
constructor Create;
destructor Destroy; override;
end;
//...
procedure TDoFinally.DoFree(O : TObject);
begin
FreeObjectList.Add(O);
end;
constructor TDoFinally.Create;
begin
FreeObjectList := TObjectList.Create(True);
end;
destructor TDoFinally.Destroy;
begin
FreeObjectList.Free;
inherited;
end;
这样前面的代码块就变成了
procedure DoSomething;
var
T1, T2, T3 : TTestObject;
DoFinally : IDoFinally;
begin
DoFinally := TDoFinally.Create;
T1 := TTestObject.Create('One');
DoFinally.DoFree(T1);
T2 := TTestObject.Create('Two');
DoFinally.DoFree(T2);
T3 := TTestObject.Create('Three');
DoFinally.DoFree(T3);
// A Bunch of code;
end;
我的问题是:这行得通还是我忽略了什么?
在我看来,这看起来很酷,并且通过减少嵌套量使代码更易于阅读。它还可以扩展为存储匿名方法列表以运行以执行诸如关闭文件、查询等操作...
【问题讨论】:
-
我真的不喜欢这种方法。它实际上使代码 less 可读。当然,它最大限度地减少了您必须阅读的代码量,但您只会使事情复杂化。
-
编译器会放入一个隐藏的try-finally块,以确保接口递减(并释放)。
-
没错,@Nicholas。这有问题吗?
-
@JerryDodge 我认为,每当您偏离“标准”Delphi 编码实践时,您都会使代码更难理解(对于除作者之外的任何人)——即使它更简单。请参阅 Rob Kennedy 使用 JCL 的答案 - 它更短更干净。我的目标更多是删除所有额外的东西,以便业务逻辑易于遵循。
-
另外不要忘记,如果内存出现问题,
Add()会引发异常,因此您必须使用try/except块来确保未跟踪的对象仍然被释放。跨度>
标签: delphi interface try-catch