AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Delphi merkt nicht wenn ein case-Statement vollständig ist, oder?
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi merkt nicht wenn ein case-Statement vollständig ist, oder?

Ein Thema von Der schöne Günther · begonnen am 2. Dez 2021 · letzter Beitrag vom 21. Nov 2024
Antwort Antwort
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.652 Beiträge
 
Delphi 12 Athens
 
#1

AW: Delphi merkt nicht wenn ein case-Statement vollständig ist, oder?

  Alt 20. Nov 2024, 17:57
So richtig sehe ich den Mehrwert noch nicht.
Einen Mehrwert wollte ich auch gar nicht demonstrieren. Es geht mir eher darum Anwendungsfälle aufzuzeigen, bei denen ein unvollständiges case im Kontext durchaus vollständig sein kann. Dann würde ein Error-Mechanismus wie oben beschrieben zu einem unnötigen Workaround-Aufwand führen um die Fehlermeldung (vermutlich sollte es vielleicht doch eher nur eine Warnung oder ein Hinweis sein) zu beseitigen. Immerhin kann der Fehler im obigen Code gar nicht auftreten - zumindest nicht in den case-Anweisungen.

Diese ganze Diskussion ist eh nur theoretisch, da sie allenfalls case-Anweisungen ohne else-Zweig beträfe. Nur so könnte man das durchziehen ohne bestehenden Code plötzlich als fehlerhaft zu diffamieren. (Ich gehe dabei mal davon aus, dass der Entwickler weiß was er tut.)

Insofern sind die im Code vorhandenen else-Zweige eigentlich auch obsolet und decken lediglich den Fall ab, dass die vorhergehende if-Anweisung klammheimlich erweitert und dabei die case-Anweisung nicht mitgezogen wird.

Im Übrigen ist der Code auch nicht ganz korrekt in Bezug auf den record helper (und ein fehlendes then). Kommt davon wenn man Code im Web-Editor eingibt anstatt in der IDE.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.175 Beiträge
 
Delphi 12 Athens
 
#2

AW: Delphi merkt nicht wenn ein case-Statement vollständig ist, oder?

  Alt 21. Nov 2024, 07:18
So richtig sehe ich den Mehrwert noch nicht.
Einen Mehrwert wollte ich auch gar nicht demonstrieren. Es geht mir eher darum Anwendungsfälle aufzuzeigen...
Sorry, auch Anwendungsfälle sehe ich für einen Guard vorab nicht unbedingt, statt diesen zentral am Ende im else-Zweig durchzuführen.
Der Vorab-Guard nimmt nur Performance und hilft meiner Meinung nach noch nicht mal bessere Lesbarkeit durch Gruppierung zu erzeugen.
Ich bleibe bei Version HandleRating2.
Trotzdem interessiert mich ein echtes Beispiel, wo das "if x in" gegenüber das "case x of" klar gewinnt, denn Ersteres nutze ich eigentlich so gut wie nie.
Das liegt vielleicht daran, dass ich seit C sehr in das switch bzw. case of verliebt bin

Das Beispiel habe ich mal entsprechend erweitert, ist ausführbar, um alle Fälle auszutesten:

Delphi-Quellcode:

type
{$SCOPEDENUMS ON}
  //(1) Wegfall eines Enums ==> Compilierfehler
// TRating = (undefined, Perfect, { OK, } Acceptable, NotGoodEnough, Bad, TotalShit);

  //(2) Zusätzliches, positives Enum NochWasGutes
  TRating = (undefined, Perfect, OK, NochWasGutes, Acceptable, NotGoodEnough, Bad, TotalShit);

  //(3) Zusätzliches, negatives Enum SehrSchlecht
// TRating = (undefined, Perfect, OK, NochWasGutes, Acceptable, NotGoodEnough, Bad, SehrSchlecht, TotalShit );

  //(4) Zusätzliches, negatives Enum am Ende SehrSchlecht OutOfRange
// TRating = (undefined, Perfect, OK, NochWasGutes, Acceptable, NotGoodEnough, Bad, SehrSchlecht, TotalShit, OutOfRange );

  //(5) Behandelt Undefined
// TRating = (Undefined, Perfect, OK, NochWasGutes, Acceptable, NotGoodEnough, Bad, SehrSchlecht, TotalShit, OutOfRange );


  TRatingHelper = record helper for TRating
    procedure HandleIncompleteCase;
  end;

procedure TRatingHelper.HandleIncompleteCase;
begin
  var LName := TRttiEnumerationType.GetName( Self );
  raise Exception.Create('unhandled case for TRating: ' + LName );
end;

const
  //cRatingPositive = [TRating.Perfect, TRating.OK, TRating.Acceptable];

  //(A) Funktioniert nur, wenn die Ratings als SubRange definiert werden können
  cRatingPositive = [TRating.Perfect .. TRating.Acceptable ];
  cRatingNegative = [TRating.NotGoodEnough .. TRating.TotalShit ];

  //(B) Funktioniert noch besser, wenn die äußeren Grenzen mit High/Low definiert werden können
  // Starte NICHT ab Undefined bis zum letzten
// cRatingPositive = [ Succ(Low(TRating)) .. TRating.Acceptable ];
// cRatingNegative = [ TRating.NotGoodEnough .. High(TRating), ];

  //(C) Funktioniert noch besser, wenn die äußeren Grenzen mit High/Low definiert werden können
  // Starte NICHT ab Undefined bis zum letzten gültigen Enum
// cRatingPositive = [ Succ(Low(TRating)) .. TRating.Acceptable ];
// cRatingNegative = [ TRating.NotGoodEnough .. TRating.TotalShit ];



procedure HandleRating1(Rating: TRating);
begin

  if Rating in cRatingPositive then begin
    // Handle positive rating part 1 //<== (1) Kommt hier rein, wenn es einen neuen Positiven gibt

    // Handle specific rating
    case Rating of
      TRating.Perfect: ;
      TRating.OK: ; //<== (1) Compile-Error bei Wegfall eines Enums
      TRating.Acceptable: ;
    else
       Rating.HandleIncompleteCase; //(2)(3) Runtime-Error: "NochWasGutes", Wenn es einen neuen Positiven gibt
    end;
    // Handle positive rating part 2

  end
  else if Rating in cRatingNegative then begin
    // Handle negative rating part 1

    // Handle specific rating
    case Rating of
      TRating.NotGoodEnough: ;
      TRating.Bad: ;
      TRating.TotalShit: ;
    else
      Rating.HandleIncompleteCase; //(3)(4) Runtime-Error: "SehrSchlecht", Wenn es einen neuen Negativen gibt
    end;
    // Handle negative rating part 2

  end
  else begin
    // (4)(5) Handle Undefined or OutOfRange rating
    Rating.HandleIncompleteCase;
  end;

end;


procedure HandleRating2(Rating: TRating);
begin

   // Handle specific rating
   case Rating of
     TRating.Perfect: ;
     TRating.OK: ; //<== (1) Compile-Error bei Wegfall eines Enums
     TRating.Acceptable: ;

   // Handle specific rating
     TRating.NotGoodEnough: ;
     TRating.Bad: ;
     TRating.TotalShit: ;
   else
     Rating.HandleIncompleteCase; //(2)(3)(4)(5) Runtime-Error: "NochWasGutes", "SehrSchlecht", Zentral, für alle
                                    // Könnte notfalls hier in Gruppen zerlegt werden, was nur im Fehlerfall Performance braucht
   end;

end;



procedure Test;
begin
    var LRating := TRating.NochWasGutes; // (2)
// var LRating := TRating.SehrSchlecht; // (3)
// var LRating := TRating.OutOfRange; // (4)
// var LRating := TRating.Undefined; // (5)

    HandleRating1( LRating ); //RunTime-Fehler, wenn es was neues, Positives/Negatives gibt

// HandleRating2( LRating ); //RunTime-Fehler, wenn es was neues, Positives/Negatives gibt

end;

Geändert von Rollo62 (21. Nov 2024 um 07:21 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz