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.