I have never seen any objections for the nested try/finally's especially when classes depend on each other.
OTOH Marco's example is a valid one, but lacks a little defensive programming if the class instances depend on each other. I would suggest to combine Marco's example with assertions (Assert(Assigned..) during development. Assertions disappear when turned off for a production build. My opinion is that if it is just for shorthand, think again. This will not help, though, if the creation depends on a dynamic code path.
Anyway. There's ARC in the pipeline and that will solve it partially.
You could also consider something like this (note: may be trunk only!):
unit smartptrs;
{ free interpretation - with very few changes! - from an example by Marco Cantu}
{$ifdef fpc}{$mode delphi}{$endif}
interface
type
Smart<T:class, constructor> = record
strict private
FValue:T;
FFreeTheValue:IInterface;
function GetValue:T;
type
TFreeTheValue = class(TInterfacedObject)
private
fObjectToFree:TObject;
public
constructor Create(anObjectToFree: TObject);
destructor Destroy;override;
end;
public
constructor Create(AValue: T);overload;
procedure Create;overload;
class operator Implicit(AValue: T):Smart<T>;
class operator Implicit(smart: Smart<T>):T;
property value: T read GetValue;
end;
implementation
constructor Smart<T>.TFreeTheValue.Create(anObjectToFree:TObject);
begin
self.fObjectToFree := anObjectToFree;
end;
destructor Smart<T>.TFreeTheValue.Destroy;
begin
fObjectToFree.Free;
inherited;
end;
constructor Smart<T>.Create(AValue:T);
begin
FValue := AValue;
FFreeTheValue := TFreeTheValue.Create(FValue);
end;
procedure Smart<T>.Create;
begin
Smart<T>.Create(T.Create);
end;
class operator Smart<t>.Implicit(AValue:T):Smart<T>;
begin
Result := Smart<T>.Create(AValue);
end;
class operator Smart<T>.Implicit(smart: Smart<T>):T;
begin
Result := Smart.Value;
end;
function Smart<T>.GetValue:T;
begin
if not Assigned(FFreeTheValue) then
Self := Smart<T>.Create(T.Create);
Result := FValue;
end;
end.
Test:
program project1;
{$mode delphi}{$apptype console}{$H+}
uses classes, smartptrs;
var
a:TStrings;
b:Smart<TStringlist>;
c:Smart<TStringlist>;
begin
a := b.value;
a.add('test');
writeln(a.text);
c.value.Add('test some more');
writeln(c.value.text);
readln;
// all cleanup is automatic
end.
Not really impractical then? Anyway. We will get something even "better" in the future. (I still have doubts about ARC)