Thema: as

Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: as

  Alt 30. Nov 2012, 19:11
Zitat:
dass ich as sehr selten nutze, da ich von meiner Einstellung her keine Überraschungen mag und somit auch keine Fehlermeldungen
Da ist deine Einstellung genau falschrum, in Bezug auf deine Fehlererwartung.

AS wirf nur eine Exception, wenn sich die Objektinstanz nicht casten läßt, da das Objekt nicht dem dem angegebenen Typen entspricht, bzw. kein Nachfahre davon ist.

Und genau da ist diese Exception vollkommen in Ordnung.


Viel schlimmer wäre es, wenn du eine inkompatibles Objekt hart castes, was dann eventuell erst irgendwo später Exceptions wirft, z.B. wenn man auf etwas nicht existierendes, oder schlimmer noch auf etwas Falsches zugreift.
Oder ganz gemein, wenn der Zugriff keinen Fehler sofort wirft, aber natürlich auch nicht das macht, was man wollte ... da könnte ein Fehler oder vieleicht eine Exception erst viel später auftreten, was dann oftmals fast garnicht mehr nachvollziehbar ist.

Dort hast du es nämlich wesentlich schwerer, die (eigentliche) Ursache zu finden.

Also wenn Cast, dann gibt es nur zwei/drei mögliche Wege:
- man weiß 100,1 %-ig, daß wirklich immer nur dieser Typ ankommt, dann kann man bedenkenlos hart casten
- man kann nicht sicher sein, dann muß es geprüft werden

- weiß man den Typ nur nicht und will entscheidend reagieren, dann vorher mit IS prüfen und eine Auswahl treffen (danach kann gerne hart gekastet werden, da IS ja sicher geprüft hat)

- will/muß man auf etwas zugreifen, dann muß der Typ 100%ig sicher sein, dann womit man dort mit AS castet. (außer man hat vorher mit IS geprüft)
- wenn man mehrfach auf das Objekt zugreift, dann kann man vorher mit IS prüfen und wenn nicht, dann eine Exception werfen oder eine Assertion einsetzen (welches sich im Release deaktivieren läßt, wenn man den Code 100%ig auf Korrektheit geprüft hat)



PS:
IS ist eine fehlerlose Prüfung, welche einen Boolean zurückgibt, wenn das keine kompatible Instanz des gewünschten Typs ist.
AS ist ein prüfender Cast, welcher den gecastete Instanz-Zeiger zurückgibt und intern "theoretisch" ein IS aufruft.
obj.InheritsFrom entspricht quasi einem IS, auér daß dort natürlich eine Instanz (kein NIL) vorhanden sein muß, da man ja sonst die Methode nicht aufrufen kann.
(OK, man hätte das NIL bei Letzerem theoretisch im Code abfangen können, aber es gibt an der Stelle wenistens eine verständliche Zugriffsverletzung durch Lesen von Adresse $00000000)

Aber:
IS ist nur erfolgreich (True), wenn in der Variable ein Objekt enthalten ist (nicht NIL) und wenn es sich bei der Instanz um den gewünschten Typen oder einen Nachfahren handelt.
AS dagegen läßt auch NIL erfolgreich durch.

Also theoretisch müßte man beim AS auch noch mit Assigned prüfen,
aber praktisch ist es nicht so schlimm, wie es klingt, denn ein NIL erzeugt beim Zugriff eine (zuverlässige) definierte Fehlermeldung (siehe InheritsFrom), welche sich problemlos zurückverfolgen kann, da man nur von der Fehlerstelle zurückgehen muß, bis dahin von wo der Wert (nil) gekommen ist.


Delphi-Quellcode:
var
  Obj: TObject;
  X, Y: TList;
begin
  Obj := nil;

  if Obj is TList then
    ShowMessage('jupp');

  try
    if Obj.InheritsFrom(TList) then
      ShowMessage('jo');
  except
    on E: Exception do
      ShowMessage(E.ClassName + ': ' + E.Message);
  end;

  Y := TList(Obj);
  X := Obj as TList;

  if X = Y then ; // damit der Compiler nix wegoptimiert
end;


Ach ja, wenn man ganz paranoid ist, dann darf man gerne alle eingehenden Parameter prüfen,
aber da Delphi eine recht strikte Typenprüfung besitzt, darf man gerne davon ausgehen, daß ein Parameter/Variable/Feld/... mindestens diesem Typen entspricht oder nil ist.
Falls doch irgendwo ein Idiot absichtlich, bzw. grob fahrlässig, diese Typenprüfung umgeht und ein total inkompatibles Objekt dort reinhackt, dann ist das halt so und und man darf es beruhigt unkontroliert knallen lassen.

Soll heißen: Wenn man eine Variable TList hat, dann ist dort einfach immer nur mindestens eine TList (oder Nachfahre) oder Nichts (nil) drinnen
und Falls doch mal ein TEdit da reingeraten ist ... Pech.
$2B or not $2B

Geändert von himitsu (30. Nov 2012 um 19:22 Uhr)
  Mit Zitat antworten Zitat