Einzelnen Beitrag anzeigen

Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#14

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 17:59
Also generell sollte man einen Konstruktor so schreiben das er keine Exception auslösen kann!!!
Das heisst also keine Resouren (mit Ausnahme von Speicher) belegen, keine Dateioperationen, keine problematischen Windows-API-Aufrufe, usw.

Die Folge ist aber, dass man dann evtl. ein unvollständig initialisiertes Objekt erhält.
Diesen Zustand kann man aber dadurch abhelfen, dass man eine Setup-Methode hat, die das Objekt vollständig initialisiert:
Delphi-Quellcode:
var
  meinobj : TMyClass;
begin
  meinobj := TMyClass.Create;
  try
    meinobj.Setup;
    mainobj.MachwasDamit;
  finally
    meinobj.Free;
  end;
Dies hat aber den unschönen Effekt, dass man mehr Schreibarbeit hat und dass man den Aufruf von Setup auch mal vergessen kann.
Dem kann aber abgeholfen werden, indem man die Setup-Methode so schreibt:
Delphi-Quellcode:
type
  TMyClass=class(TObject)
  private
    FSetupDone : Boolean;
  protected
    procedure Setup;virtual;
  public
    procedure MachWasDamit;
  end;

procedure TMyClass.Setup;
begin
  if not FSetupDone then
  begin
    // hier der Code der nicht in den Konstruktor soll, weil er potentiell eine Exception
    // auslösen kann
    ...
    FSetupDone := True;
  end;
end;

procedure TMyClass.MachWasDamit;
begin
  Setup; // wird jeder Methode von TMyClass aufgerufen, damit sichergestellt wird
  // dass das Objekt vollständig initialisert ist

  // hier der Code von MachWasDamit
  ..
end;
Ok, diese Methode bedeutet mehr Schreibarbeit und auch eine minimale Performanceverschlechterung aber man vermeidet so eine Exception im Konstruktor mit allen seinen hässlichen Konsequenzen.

Es gibt auch noch andere Möglichkeiten um Code im Konstruktor zu vermeiden, der potentiell eine Exception auslösen kann.
Stichwort: Dependeny Injection

Angenommen ein Thread soll in eine Datei loggen.
Im naiven Ansatz würde man das so machen:
Delphi-Quellcode:
constructor TMyThread.Create;
begin
  inherited Create;
  FLogger := TLogger.Create;
  // Gefahr!
  // hier kann eine Exception ausgelöst werden (z.B. keine Schreibrechte auf der Lodatei)
  FLogger.OpenLogfile('C:\log.txt');
end;
Bei der Dependency Injection würde die Threadklasse verlangen, dass ein geöffnetes (!) Logobjekt übergeben wird:
Delphi-Quellcode:
constructor TMyThread.Create(logger:TLogger);
begin
  inherited Create;
  FLogger := logger; // das ist sicher; keine Exception möglich
end;
  Mit Zitat antworten Zitat