Registriert seit: 15. Mär 2007
4.093 Beiträge
Delphi 12 Athens
|
AW: Delphi merkt nicht wenn ein case-Statement vollständig ist, oder?
Heute, 08: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 (Heute um 08:21 Uhr)
|