Hallo Motzi,
Zitat von
Motzi:
as prüft [..] nochmal [..] ob der Cast korrekt ist und löst gegebenenfalls eine
Exception aus
Das ist wahr sollte aber idR nicht ins Gewicht fallen: Zwar hängt die Ausführungszeit stark von der Tiefe der Hierarchie ab, aber bei einem ~1.2GHz Rechner konnte ich mit einer Tiefe von 8 Ebenen knapp 17 Millionen Ergebnisse pro Sekunde vom
is Operator verzeichnen.
Für mich stellt sich, gerade bei einem Anfänger-Tutorial eher die Frage nach der Konsistenz. Sowohl bei Ereignisbehandlungsroutinen
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
with Sender as TButton do
Caption:= AMethod;
,die "eigentlich nur von einem Button" aufgerufen werden sollten, als auch bei sonstigen Parametern kann eine zusätzliche und dabei so effiziente Form der Überprüfung nicht schaden.
Häufig schon habe ich gesehen, dass zu einem späteren Zeitpunkt solche Routinen auch mit einem NotifyEvent einer anderen Klasse (zB dem
OnChange-Event eines Edits) verknüpft werden und dann- im Fall eines nicht abgesicherten Casts zu Problemen führen.
Bei Interfaces hingegen ist die Problematik noch schwerwiegender: Ein Konstrukt der Art
Delphi-Quellcode:
procedure SomeTest(const AReference: IInterface);
begin
if Supports(AReference, IMyInterface) then
IMyInterface(AReference).AMethod;
wird zwar kompiliert werden, kann aber trotz des erfolgreichen Tests (
Supports) zu Fehlern führen, wenn in diesem Fall die Routine
SomeTest in dieser (nicht seltenen) Form aufgerufen wird, die sich mit allen Deklarationen und Typen deckt, also keinen Fehler zur Compilierzeit hervorruft:
Delphi-Quellcode:
type
TMyClass = class(TMyAncestor, IInterface, IMyInterface)
end;
//..
var
myRef: IInterface;
begin
myRef:= TMyClass.Create;
SomeTest(myRef);
Eine Lösung mit
as innerhalb von
SomeTest hingegen arbeitet fehlerfrei.
Weil einem Anfänger so gesagt werden kann: "Verwende immer
as und nur
as, um einen Cast durchzuführen" wird er den direkten Cast meiden und kann auch nicht in Versuchung geführt Konstrukte der Art
Delphi-Quellcode:
var
s: string[4];
begin
Integer(s):= $badfood;
zu verwenden, um vermeintlich einiges an Performance herauszuholen, dabei aber Randbedingungen zu übersehen...