![]() |
Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Hallo,
ich möchte bei einer Case-Anweisung einen Compiler-Fehler bekommen wenn ein neues Element der Enumeration hinzugefügt wird. Damit der Schritt zwingend ausprogrammiert wird. Delphi gibt da nicht mal eine Warnung oder Hinweis aus. Ich hab es auch schon versucht mit einer Hilfsvariable um die Warnung W1036 zu bekommen und die Warnung in dem Block dann als Fehler kennzeichnen. Funktioniert aber leider nicht wie erwartet. Hat jemand eine Idee wie man das lösen könnte?
Delphi-Quellcode:
type
TEnum = ( t1, t2, t3); var lEnum: TEnum; lEnumCheck: Boolean; begin {$WARN USE_BEFORE_DEF ERROR} lEnum := t1; case lEnum of t1: lEnumCheck := True; t2: lEnumCheck := True; // t3: lCheck := True; end; if lEnumCheck then //Warnung ist hier wenn t3 auskommentiert ist bekomme aber keinen Fehler, wenn t3 wieder drin ist ist die Warnung ganz am Ende der Prozedur. Packe ich das {$WARN USE_BEFORE_DEF DEFAULT} nach dem end dann kriege ich in jedem Fall ein Fehler. begin end; {$WARN USE_BEFORE_DEF DEFAULT} end; |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Wie wäre es mit einem ganz anderen Ansatz?
Delphi-Quellcode:
Wenn jetzt TEnum um weitere Elemente erweitert wird, muss zwangsläufig auch die Konstante erweitert werden. Eine andere Möglichkeit wäre so etwas:
type
TEnum = (t1, t2, t3); const EnumCheck: array[TEnum] of Boolean = (true, true, false);
Delphi-Quellcode:
function EnumCheck(Value: TEnum): Boolean;
begin case Value of t1: Result := true; t2: Result := true; else raise EForgottenValue.Create('Hamwa nich was vergessen?'); end; end; |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Delphi-Quellcode:
Schnell hingekrakelt, Tippfehler inklusive ...
type
TEnum = ( t1, t2, t3); const CEnum : array[ TEnum ] of String = ( 't1', 't2', 't3' ); //Knallt schon hier, wenn es nicht übereinstimmt var lEnum: TEnum; lEnumCheck: Boolean; begin CEnum[ t1 ]; end; @DeddyH: Ey, mach mal langsamer, damit ich auch noch eine Chance habe :-D |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Das entspricht doch meinem ersten Vorschlag, oder nicht?
[edit]@Rollo62: ich gelobe Besserung :mrgreen:[/edit] |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
vielleicht so?
Delphi-Quellcode:
case Value of
t1: Result := true; t2: Result := true; {$IF High(TEnum) <> t2} {$MESSAGE Error 'peng'} {$IFEND} end; |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Ich möchte aber gerne direkt beim case hängen bleiben. Nur weil ich dann die Konstante erweitert habe, habe ich mein case ja nicht angepasst. Wenn ich mehrere case-anweisungen habe die ich beachten muss, müsste ich ja so eine Zuweisung über jede case-Anweisung von dieser Enumeration machen. Den zweiten Fall mache ich auch schon. Das bekomme ich aber erst zur Laufzeit mit. Hätte es halt gerne direkt beim kompilieren. Unit-Test wäre das einzige was mir noch einfällt. Hätte es aber wie gesagt gerne schon direkt beim kompilieren als Fehler, damit man direkt dahin geführt wird und das ausprogrammieren kann. |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Funktioniert z.B. nicht wenn jemand mittendrin ein Element einträgt (auch wenn man sowas lieber nicht machen sollte). Und wenn man die Bedingung unten anpasst ohne den neuen Case-Fall hinzuzufügen würde man das ja auch schon umgehen. Kann man denn evtl. mit den Compiler-Direktiven eine variable Hochzählen? Hab dazu nichts gefunden. Damit könnte ich ja für jeden Case-Fall die Variable hochzählen und dann gegen "Ord(High(TEnum))" checken. |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Delphi-Quellcode:
{$IF Ord(High(TENum) <> 1}{$MESSAGE Error 'peng'} {$IFEND}
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Das ist so aber auch schwer mitzubekommen,
bzw. es wird nicht lesbarer. :stupid:
Delphi-Quellcode:
{$IF Ord(High(TEnum)) <> 1} {$MESSAGE Error 'peng'} {$IFEND}
Delphi-Quellcode:
array[TEnum] of ... = (...);
Hier bekommst du die Änderung der Anzahl mit. Wenn jemand aber gleichzeitig etwas hinzufügt und löscht, ohne dass es zwischendrin angepasst wurde, dann flutscht das natürlich durch. |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Meine Idee mit dem Ord(High(TEnum)) war so gedacht:
Delphi-Quellcode:
type
TEnum = ( t1, t2, t3); var lEnum: TEnum; begin {$DEFINE ENUMCOUNT 0} case lEnum of t1: begin {$DEFINE ENUMCOUNT ENUMCOUNT+1} ... end; t2: begin {$DEFINE ENUMCOUNT ENUMCOUNT+1} ... end; // Hier immer letztes Element aus der Case-Anweisung eintragen. {$IF Ord(High(TEnum)) <> ENUMCOUNT} {$MESSAGE Error 'Case-Fall fuer jedes Element ausprogrammieren!'} {$IFEND} else raise Exception.Create('Fehlermeldung'); end; end; |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Siehe auch:
![]() und Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Zitat:
Delphi-Quellcode:
Dass man das jetzt erweitern muss, ist ja genau Sinn des Crashes.
CEnum : array[ TEnum ] of String = ( 't1', 't2', 't3' ); //Knallt schon hier, wenn es nicht übereinstimmt
Nebenbei hätte so eine noch weitere Vorteile, also zum Beispiel Textausgabe, Rückgabe beliebiger Werte, etc. Eventuell sucht Du ja sowas, etwas "Verboseres":
Delphi-Quellcode:
type
TMyEnum = (Value0, Value1, Value2); const ExpectedEnumSize = 3; // Erwartete Anzahl der Elemente in TMyEnum {$IF Ord(High(TMyEnum)) > (ExpectedEnumSize-1) } {$MESSAGE ERROR 'TMyEnum wurde erweitert!' } {$ELSEIF Ord(High(TMyEnum)) < (ExpectedEnumSize-1) } {$MESSAGE ERROR 'TMyEnum wurde verkleinert!' } {$IFEND} |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Er muß ja keinen Fehler werfen, aber z.B. eine Warnung oder Info wäre eigentlich problemlos möglich, wenn bei einem Enum nicht alle Werte benutzt wurden.
Ja, natürlich auch abschaltbar, bzw. vielleicht über ein Attribut oder Keyword, explizit anforderbar, denn es kommt vor, dass ich in manchen Case absichtlich garnicht alles verwende, z.B. wenn an einer Stelle nur ein Teil benötigt wird und der Rest einfach nichts machen soll. |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Delphi-Quellcode:
case bla of
b1: HandleB1; b2: HandleB2; else // nix tun end; |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Das wäre mal eine interessante IDE-Funktion: Man tippt einen Enum-Wert und die IDE schlägt automatisch einen Scope vor. Also quasi ein umgekehrtes TEnumType.<ctrl+Space> Oder gibt's das am Ende schon? |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Zitat:
Delphi-Quellcode:
sollte daraus dann TEnumTyp.EnumWErt1 machen.type TEnumTyp = (enumWert1, enumWert2); if SomeEnumVariable = enumWert1<Tastatur-Shortcut-drücken> |
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Liste der Anhänge anzeigen (Anzahl: 1)
Aber das geht ja bereits. Es muss halt auch als SCOPEDENUM deklariert sein.
|
AW: Case-Anweisung - Zwingen alle Elemente des Typen auszuprogrammieren
Wobei ich mir das manchmal andersrum wünschen würde, also einen impliziten Default-Scope.
Der Compiler weiß, welchen Typ die Variable oder der Parameter haben, wo das reinsoll. Da wäre es doch "intelligent" wenn der dann auch gleich den Scope vorgibt, wo zuerst nach dem Namen gesucht wird, damit man z.B. bei einem SET nicht dutzende Male diesen beschissenen Scope mit angeben muß. Außerdem würde es dann auch ohne ScopedEnum dann öffters den richtigen Enum erwischen, weil teilweise sind ja einige Namen doppelt/mehrfach vergeben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:04 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