5

ここにコードがあります:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  IInnerTest = interface (IInterface)
    procedure DoSth;
  end;

  TRekScannerData = record
    Source: Integer;
    Device: IInnerTest;
  end;

  ITest = interface (IInterface)
    procedure DoSth;
  end;

  ATest = class(TInterfacedObject, ITest)
  private
    FInner: Array of TRekScannerData;
  public
    procedure DoSth;
    constructor Create();
    Destructor Destroy();override;
  end;

  AInnerTest = class (TInterfacedObject, IInnerTest)
  private
    FMainInt: ITest;
  public
    constructor Create(MainInt: ITest);
    procedure DoSth;
    Destructor Destroy();override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  test: ITest;

implementation

{$R *.dfm}

{ ATest }

constructor ATest.Create;
begin
  SetLength(FInner, 1);
  FInner[0].Device := AInnerTest.Create(self);
  //<----- Here is the reason. Passing main interface to the inner interface.
end;

destructor ATest.Destroy;
begin
  beep;
  inherited;
end;

procedure ATest.DoSth;
begin
  //
end;

{ AInnerTest }

constructor AInnerTest.Create(MainInt: ITest);
begin
  FMainInt := MainInt;
end;

destructor AInnerTest.Destroy;
begin
  beep;
  inherited;
end;

procedure AInnerTest.DoSth;
begin
  //
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  test := ATest.Create;
  test.DoSth;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  test := nil;
end;

end.

問題は、test が nil に割り当てられている場合、Destroy が呼び出されないことです。

すべての内部インターフェイスを 1 つのステートメントで解放したいのですが、可能ですか? または、nil の前に別の方法を使用してすべての内部構造を破棄する必要がありますか?

編集

クラス構造は次のとおりです。

Var x = ITest(ATest class) has ->
  Inner Interface: IInnerTest(AInnerTest class) which has reference to:
    ITest(ATest class)

Nil'ing x はすべての構造を解放しません ...

4

1 に答える 1

5

循環参照があります。の実装はIInnerTestへの参照を保持しますITest。の実装はITestへの参照を保持しますIInnerTest。そして、この循環参照は、インターフェイスの参照カウントが決してゼロにならないことを意味します。

この問題の通常の解決策は、弱参照を使用することです。いくつかの便利なリンク:

于 2013-01-03T13:02:58.860 に答える