Enum (enumeraties) in Rust verschillen fundamenteel van enum in C/C++: ze kunnen geassocieerde gegevens opslaan en zijn perfect voor het modelleren van status en fouten. Hiermee worden type-veilige finite-state machines gebouwd, verschillende soorten Option/Result geïmplementeerd, en wordt het "sum types" patroon gerealiseerd. Historisch gezien werden soortgelijke constructies in functionele talen gebruikt om versies van entiteiten met strikt gescheiden varianten te beschrijven.
Probleem: Uitdrukking (de uitdrukking van alle statusvarianten) waar elke verwerkingszaak verplicht is, en het onmogelijk is om per ongeluk een tak over te slaan. Fouten op projectniveau zijn moeilijk te typen zonder zo'n expressieve structuur.
Oplossing: Enum met geassocieerde gegevens en pattern matching bieden controle — elke tak wordt door de compiler gecontroleerd, exhaustiviteit wordt gewaarborgd. Bovendien zijn er al veel hulpprogramma-methoden voor Result en Option geïmplementeerd.
Codevoorbeeld:
enum NetworkState { Disconnected, Connecting(u32), // poging nummer Connected(String), Error(String), } fn print_state(state: NetworkState) { match state { NetworkState::Disconnected => println!("Net: disconnected"), NetworkState::Connecting(count) => println!("Net: connecting (attempt {})", count), NetworkState::Connected(addr) => println!("Net: connected to {}", addr), NetworkState::Error(msg) => println!("Net error: {}", msg), } }
Belangrijke kenmerken:
Is het mogelijk om delen van enum takken te verwerken zonder _?
De compiler staat geen ongebruikte gevallen toe voor non-exhaustive enum, maar als je _ gebruikt, worden de ongebruikte takken "verwerkt". Vermijd _ bij klinisch belangrijke takken, zodat toekomstige wijzigingen niet onopgemerkt blijven.
In welke gevallen worden geassocieerde waarden doorverwezen en in welke gevallen worden ze gekopieerd bij pattern matching?
Bij pattern matching worden de geassocieerde gegevens standaard verplaatst (move). Als je alleen een weergave nodig hebt, gebruik dan verwijzingen:
match &state { NetworkState::Connected(addr) => println!("by ref: {}", addr), _ => {} }
Is het mogelijk om twee enum met overlappende varianten bij naam te gebruiken in dezelfde structuur?
Ja, maar de namen van de varianten worden gebruikt met een prefix van de enum. Dit voorkomt conflicten en maakt de code zelfdocumenterend (bijvoorbeeld, Status::Ok vs NetworkState::Ok).
_ om steeds nieuwe varianten te verbergen bij het uitbreiden van enum_ =>) in kritische foutafhandelaarsIn de code heeft de verwerking van Result<T, E> altijd een catch-all via _ =>, en nieuwe fouten (bij het uitbreiden van enum) gaan voorbij — er ontstaan silent-loss fouten.
Voordelen:
Nadelen:
Exhaustiveness matching wordt gebruikt, elke variant van Enum wordt expliciet verwerkt, of er is een panic in de tak waarvoor er geen robuust gedrag is.
Voordelen:
Nadelen: