How does EK9 prevent common enum bugs?
← Enumerations · Ref: Q226
EK9 prevents entire categories of enum bugs that plague other languages. These protections are automatic and cannot be bypassed.
EXHAUSTIVE SWITCH ENFORCEMENT
When you switch on an enum using direct constant references, the compiler verifies ALL values are covered. Adding a new value to the enum forces you to handle it everywhere. No silent missing-case bugs.
BOUNDARY TO UNSET
Incrementing past the last value or decrementing before the first produces unset, not an index error or silent wraparound. Check with ? when you need to know.
SAFE STRING CONSTRUCTION
Constructing from an invalid string returns unset, not an exception. No try-catch overhead. No risk of uncaught IllegalArgumentException crashing production.
IMMUTABLE CONSTANTS
Enum values are immutable constants. You can compare and copy them but never modify the enum definition at runtime. No reflection tricks, no monkey-patching.
NO INTEGER CASTING
EK9 enums are not integers. You cannot accidentally pass 42 where a Season is expected. The type system prevents it at compile time.
UNSET PROPAGATION
Operations on unset enums produce unset results. No NullPointerException. No undefined behaviour. The unset state flows safely through your program until you check it.
See Q73 for exhaustive switch details. See Q99 for basic enumerations. See Q219 for all auto-generated operators. See Q222 for unset semantics.
Example
defines module qa.enums.safety defines type Status Pending Active Paused Complete defines function describeStatus() as pure -> s as Status <- description <- String() //Exhaustive: compiler forces ALL values to be handled switch s case Status.Pending description: "waiting to start" case Status.Active description: "in progress" case Status.Paused description: "temporarily stopped" case Status.Complete description: "finished" default description: "no status set" defines program EnumSafetyDemo() stdout <- Stdout() // === EXHAUSTIVE SWITCH: all values must be covered === for s in Status stdout.println(`${s}: ${describeStatus(s)}`) // === BOUNDARY TO UNSET: no index errors === last <- Status.Complete last++ stdout.println(`Past last isSet: ${last?}`) first <- Status.Pending first-- stdout.println(`Before first isSet: ${first?}`) // === SAFE STRING CONSTRUCTION: no exceptions === valid <- Status("Active") stdout.println(`Valid: ${valid}, isSet: ${valid?}`) invalid <- Status("Running") stdout.println(`Invalid isSet: ${invalid?}`) // === IMMUTABLE CONSTANTS: copy, do not modify === original <- Status.Active copied <- Status(original) stdout.println(`Original: ${original}, Copy: ${copied}`) // === UNSET PROPAGATION: no null exceptions === unsetStatus <- Status() result <- unsetStatus == Status.Active stdout.println(`Unset comparison isSet: ${result?}`) unsetStr <- $unsetStatus stdout.println(`Unset string isSet: ${unsetStr?}`)
Common mistakes
E50060 — EK9 enumerations do not have a 'valueOf()' method like Java enums. Use the String constructor 'Status("Active")' for safe string construction. Invalid strings return unset instead of throwing exceptions. See ek9 -h E50060 for details.
Incorrect:
valid <- Status.valueOf("Active")
Correct:
valid <- Status("Active")
Other ways to ask this
- What enum bugs does EK9 eliminate at compile time?
- Why are EK9 enums safer than in other languages?
- How does EK9 protect against enum-related errors?
Coming from another language?
C/C++: enums are integers, any integer value accepted, no type safety, missing switch cases are optional warnings only. Java: null enum throws NullPointerException, valueOf throws IllegalArgumentException, exhaustive switch only since Java 21 with sealed types. Python: no exhaustive checking in match/case for enums, Enum construction can raise ValueError. Go: iota constants are integers with zero type safety, any int passes. Rust: exhaustive match is strong, but no boundary-to-unset or safe string construction. Kotlin: when-expression exhaustive only when used as expression, nullable enums require explicit handling. C#: integer-backed, Enum.IsDefined for runtime checking only. EK9: compile-time exhaustive switch, boundary-to-unset, safe string construction, no integer casting, unset propagation.
Keywords: exhaustive, bug, enumeration, compile, boundary, safety, prevent, switch, enum, protection, immutable