Sorununuzu çözmek için bir yaklaşım kodunuzu değiştirmektir, böylece sadece bir arabirim referansı yoluyla nesneye başvurursunuz. Başka bir deyişle yerine
var
obj: TMyObject;
...
obj := TMyObject.Create;
try
obj.DoStuff;
//etc. etc.
finally
obj.Free;
end;
Sen yaz
var
obj: IMyObject;//NOTE: interface variable
...
obj := TMyObject.Create;
obj.DoStuff;
//etc. etc.
obj := nil;//or let it go out of scope and release that way
Bu rahatsız edici olabilir, bu yüzden otomatik ömür boyu yönetimi devre dışı bırakmak daha uygun olabilir. Uyguladığınız nesne için bunu yapmanız gerekir:
type
TInterfacedObjectWithoutLifetimeManagement = class(TObject, IInterface)
private
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
function TInterfacedObjectWithoutLifetimeManagement.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TInterfacedObjectWithoutLifetimeManagement._AddRef: Integer;
begin
Result := -1;
end;
function TInterfacedObjectWithoutLifetimeManagement._Release: Integer;
begin
Result := -1;
end;
Daha sonra sınıflarınızı bu sınıftan türetebilirsiniz.
Bu yaklaşımla çok büyük bir uyarı var. TInterfacedObjectWithoutLifetimeManagement
türetilmiş bir sınıf tarafından uygulanan arabirimleri değişkenler (yerel, genel, sınıf üyesi) tuttuğunuzu varsayalım. Bu tür arayüz değişkenlerinin, uygulama nesnesinde
olarak adlandırdığınız önce sonlandırılması gerekir.
Bu kuralı uygulamamanız durumunda, bu arayüz değişkenleri kapsam dışında kaldığında, derleyici kod _Release
'i çağırmak için hala kod çıkarır ve bir nesne üzerinde bir yöntemi çağırmak için bir hata olur. yerlebir edilmiş. Bu özellikle kötü bir hata türüdür, çünkü kodunuz en önemli müşterinizin makinesinde çalışıncaya kadar bir çalışma zamanı hatası ile kendini göstermez! Diğer bir deyişle, bu tür hatalar aralıklı doğa olabilir.