Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Casts - is, as, Assert (https://www.delphipraxis.net/147238-casts-assert.html)

uligerhardt 4. Feb 2010 09:16


Casts - is, as, Assert
 
Nachdem das Thema grad mal wieder aufgetaucht ist:

Ein Cast mit "as" enthält ja eine Laufzeittypprüfung und löst bei Fehlschlag eine Exception aus. Ich hätte jetzt gern, dass die Typprüfung nur dann zuschlägt, wenn {$ASSERTIONS ON} sind. Momentan schreibe ich immer
Delphi-Quellcode:
Assert(Sender is TButton);
TButton(Sender).Caption := 'Blubb';
, aber das ist auf Dauer ganz schön umständlich für eine Funktionalität, die ich oft benutze. Kennt jemand eine schönere Lösung? Quasi
Delphi-Quellcode:
(Sender assert_as TButton).Caption := 'Blubb';
? :lol:

himitsu 4. Feb 2010 09:22

Re: Casts - is, as, Assert
 
Toll, schalltet man die Assertions ab, gibt es keine Prüfung mehr und es kommt womöglich zu undurchsichtigen Folgefehlern.

Fazit:
- wenn du nicht sicherstellen kannst, daß dort ein passendes Objekt vorliegt,
dann nutze (Sender as TButton).Caption
- wenn du die Prüfung nur wärend der Programmierphase möchtest, dann stell halt dein Assert(Sender is TButton) davor

Bernhard Geyer 4. Feb 2010 09:25

Re: Casts - is, as, Assert
 
Ich mach es immer wie Astat vorgeschlagen:

Delphi-Quellcode:
  if (Sender is TButton) then
    showmessage((Sender as TButton).Name);

mkinzler 4. Feb 2010 09:26

Re: Casts - is, as, Assert
 
Dann könnte man auch einen harten Cast machen. Ich bevorzuge aber auch diese "doppelte" Methode

himitsu 4. Feb 2010 09:30

Re: Casts - is, as, Assert
 
Delphi-Quellcode:
if (Sender is TButton) then
    showmessage((Sender as TButton).Name);
ist vollkommen unnötig, denn wenn IS meinte es wäre OK, dann ist AS an dieser Stelle unnüzt, da es eh nie anschlagen kann.

Delphi-Quellcode:
if (Sender is TButton) then
    showmessage(TButton(Sender).Name);
Dieses reicht also aus und ist sogar kürzer und, für mich zumindestens, "übersichtlicher".

PS: statt des Castes vor Ort nutze ich hier manchmal sogar "externe" Casts, in Form einer ABSOLUTE-Deklaration.

uligerhardt 4. Feb 2010 09:32

Re: Casts - is, as, Assert
 
Zitat:

Zitat von himitsu
Toll, schalltet man die Assertions ab, gibt es keine Prüfung mehr und es kommt womöglich zu undurchsichtigen Folgefehlern.

Wenn du so argumentierst, darfst du aber gar keine Assertions verwenden oder musst deine Anwendung mit eingeschalteten Assertions ausliefern.

Zitat:

Zitat von himitsu
Fazit:
- wenn du nicht sicherstellen kannst, daß dort ein passendes Objekt vorliegt,
dann nutze (Sender as TButton).Caption
- wenn du die Prüfung nur wärend der Programmierphase möchtest, dann stell halt dein Assert(Sender is TButton) davor

Genau: Version 2 möchte ich, aber ohne mich beim Programmieren wiederholen zu müssen. Wenn die Prüfung Aufwand macht, besteht ja bekanntlich die Neigung, sie ggfs. "schnell mal" wegzulassen.

himitsu 4. Feb 2010 09:51

Re: Casts - is, as, Assert
 
Zitat:

Zitat von uligerhardt
Wenn du so argumentierst, darfst du aber gar keine Assertions verwenden oder musst deine Anwendung mit eingeschalteten Assertions ausliefern..

Darum meinte ich ja, daß dieses nicht unbedingt ein optimaler Weg ist, um eventuelle Fehler abzuprüfen.

hmmmm, sowas geht leider nicht, da man hierfür ja den Typ vom Check-Parameter als Result bräuchte.
Delphi-Quellcode:
Function OCheck(O: TObject; Check: TClass): {TObject}; Inline;
  Begin
    Assert(O is Check);
    Result := O;
  End;
Delphi-Quellcode:
Function OCheck(O: TObject; Check: TClass): {TObject}; Inline;
  Begin
    {$IFOPT C+}
      If Assigned(O) Then
        Raise EAssertionFailed.CreateFmt('Object $%.8x "%s" is not %s',
          [Integer(O), O.ClassName, Check.ClassName])
      Else Raise EAssertionFailed.CreateFmt('Object (nil) is not %s', [Check.ClassName]);
    {$ENDIF}
    Result := O;
  End;

Aber wieso Aufwand?
Wenn du einmal ein Assert(Sender is TButton) an den Anfang der Prozedur stellt, dann brauchst du danach doch nichts mehr machen?

Delphi-Quellcode:
Procedure X(Obj: TObject);
  Var O: TButton absolute Obj:

  Begin
    Assert(Obj is TButton);
    ...
    O.Caption := 'ich bin ein Button';
    ...
  End;
Dieses prüft nur wärend der Programmierpfase und mit aktiven Assertions.

Wobei ich es meißt eher so mach:
Delphi-Quellcode:
Procedure X(Obj: TObject);
  Var O: TButton absolute Obj:

  Begin
    If Obj is TButton Then Begin
      ...
      O.Caption := 'ich bin ein Button';
      ...
    End Else {mach was, wenn es kein Button ist};
  End;

uligerhardt 4. Feb 2010 10:08

Re: Casts - is, as, Assert
 
Mir ist das immer OK erschienen: Während der Entwicklungs- und Testphase prüft mein Ereignishandler, dass ihm auch wirklich nur Buttons reingereicht werden. Danach bin ich hinreichend davon überzeugt, dass meine Programmierung passt, und kan auf die Typprüfung verzichten.

Zitat:

Zitat von himitsu
hmmmm, sowas geht leider nicht, da man hierfür ja den Typ vom Check-Parameter als Result bräuchte.
Delphi-Quellcode:
Function OCheck(O: TObject; Check: TClass): {TObject}; Inline;
  Begin
    Assert(O is Check);
    Result := O;
  End;
Delphi-Quellcode:
Function OCheck(O: TObject; Check: TClass): {TObject}; Inline;
  Begin
    {$IFOPT C+}
      If Assigned(O) Then
        Raise EAssertionFailed.CreateFmt('Object $%.8x "%s" is not %s',
          [Integer(O), O.ClassName, Check.ClassName])
      Else Raise EAssertionFailed.CreateFmt('Object (nil) is not %s', [Check.ClassName]);
    {$ENDIF}
    Result := O;
  End;

Mit so Ähnlichem hab ich auch schon rumgespielt. Aber ich fürchte, ohne Compilerunterstützung ist da nix zu machen. :-/

Zitat:

Zitat von himitsu
Aber wieso Aufwand?
Wenn du einmal ein Assert(Sender is TButton) an den Anfang der Prozedur stellt, dann brauchst du danach doch nichts mehr machen?

Naja, das sind halt trotzdem 2, im echten Leben manchmal auch 3 oder 4 Zeilen, wo meinem Empfinden nach eine reichen müsste. Und das Ganze mit reichlich Wiederholungen (== Fehlerquellen).


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz