Проверить экземпляр свободного объекта - PullRequest
0 голосов
/ 13 апреля 2019

У меня следующая структура класса.

TObjectA = class
    ...
end;

TObjectB = class
    private
        FDependencyObjectA
    public
        constructor Create(const DependencyA: TObjectA);
        destructor Destroy; override;
end;

{ TObjectB }

constructor TObjectB.Create(const DependencyA: TObjectA);
begin
    FDependencyObjectA := DependencyA;
end;

destructor TObjectB.Destroy;
begin
  FDependencyObjectA.Free;
  FDependencyObjectA := nil; 
  inherited;
end;

Я пытаюсь найти решение для работы с этими двумя вариантами использования.

// Use cases

// First case 
// Works with Free on Destroyer
// Does not work without Free on Destroyer
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectB: TObjectB;
begin
   ObjectB := TObjectB.Create(TObjectA.Create);
   try
       ...
   finally
       ObjectB.Free; 
   end;
end;


// Second case
// Does not work with Free on Destroyer
// Works without Free on Destroyer
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectA: TObjectA;
 ObjectB: TObjectB;
begin
   ObjectA := TObjectA.Create;
   ObjectB := TObjectB.Create(ObjectA);
   try
       ...
   finally
       // Depending on the implementation of the Destroyer or the this finally
       // Can raise Access Violation, Invalid Pointer or Memory Leak
       ObjectB.Free; 
       ObjectA.Free;
   end;
end;

Одним из решений будет проверкачто ObjectA уже свободен от памяти.Но я не знаю проверки только тогда, когда объект свободен, я знаю проверки того, когда объект нулевой.

// Third case (Trying for a solution)
procedure TForm1.Button1Click(Sender: TObject);
var
 ObjectA: TObjectA;
 ObjectB: TObjectB;
begin
   ObjectA := TObjectA.Create;
   ObjectB := TObjectB.Create(ObjectA);
   try
       ...
   finally
       ObjectB.Free;       
       // It would work fine if Assigned returned false, but always returns true
       if Assigned(ObjectA) then  // or ObjectA <> nil
         ObjectA.Free;
         // If I use just assign nil instead of Free, compile throws a hint
         // ObjectA := nil;
         // H2077 Value assigned to 'Your_Variable' never used
   end;
end;

Другим решением будет внедрение зависимости с использованием зарезервированного слова var.Но сначала я хочу оценить другие возможности.

В Delphi есть ли способ проверить, является ли объект просто свободным и не только нулевым?

Или есть ли обходной путь для работы с первымдва варианта использования, без ошибок Access Violation, Invalid Pointer, Memory Leak или Compile Hints?

Я не просто хотел принять только один вариант использования, или мне приходилось постоянно проверять разрушитель объекта, чтобы знать, как реализоватьновая функция / процедура.Это плохо для повседневных реализаций или когда в проект вступает новый разработчик.Мы должны были бы объяснить все эти маленькие правила, а также постоянно проверять правильность реализаций.

Редактировать:

Я знаю, что в Delphi есть ARC для интерфейсов, ноне все объекты реализуют интерфейс.

Для подсказок есть директива компиляции {$ Hints Off}, но в любом случае добавление этой директивы не очень эффективно.

1 Ответ

1 голос
/ 13 апреля 2019

Правильный код такой:

ObjectA := TObjectA.Create;
ObjectB := TObjectB.Create(ObjectA);
try
  ...
finally
  ObjectB.Free;       
end;

ObjectB вступает во владение ObjectA, и поэтому его задача - уничтожить его.Код вызова передал эту ответственность и поэтому больше ничего не должен делать.

...