Вызов Free
по нулевой ссылке всегда безопасен. Посмотрите в реализации TObject.Free
, чтобы понять, почему.
Этот код является примером заводской функции . Его задача заключается в создании нового экземпляра класса, но в случае его сбоя необходимо убедиться, что он не пропускает наполовину созданный экземпляр, когда выдает исключение, поэтому он вызывает Free
. Когда он уверен, что получится, он передает право собственности на результат вызывающей стороне. Он по-прежнему вызывает Free
, но если это уже переданное право собственности, то в итоге он вызывает Free
по нулевой ссылке, и никакого вреда не будет. Этот код является то, что передает право собственности:
Result := Connection;
Connection := nil;
То, как I напишет фабричную функцию, избавит от отдельной переменной Connection
. Я бы построил результат непосредственно в Result
, но освободил бы его, если бы было исключение, например:
function TDBXConnectionFactory.GetConnection(const DBXContext: TDBXContext;
const ConnectionProperties: TDBXProperties): TDBXConnection;
var
ConnectionBuilder: TDBXConnectionBuilder;
DelegatePath: TDBXDelegateItem;
Connection: TDBXConnection;
CombinedProperties: TDBXProperties;
begin
//...
ConnectionBuilder := TDBXConnectionBuilder.Create;
try
//..lots of setting ConnectionBuilder properties
ConnectionBuilder.FInputPassword := CombinedProperties[TDBXPropertyNames.Password];
Result := ConnectionBuilder.CreateConnection;
try
Result.Open;
except
Result.Free;
raise;
end;
finally
ConnectionBuilder.Free;
end;
end;
Это имеет тот же эффект.