on Apr 29th 2025
This article is aimed at developers who already know how to develop software using C#, to show how enums work in Rust, and to explore the alternatives for doing the same things we are used to doing in C#, as well as the new possibilities offered in Rust.
If you want to learn more about enums, please, read the official documentation.
The main difference is the way we call the enum to use it.
```csharp // C# enum Country { Brazil, England, UnitedStates }
// ... Country country = Country.Brazil; ```
```rust // Rust enum Country { Brazil, England, UnitedStates }
// ... let country: Country = Country::Brazil; ```
Almost no difference between C# and Rust.
```csharp // C# enum HttpStatus { OK = 200, NotFound = 404 }
// ... HttpStatus status = HttpStatus.OK; int statusCode = (int)HttpStatus.OK; ```
```rust // Rust enum HttpStatus { OK = 200, NotFound = 404, }
// ... let status: HttpStatus = HttpStatus::OK; let statusCode: i32 = HttpStatus::OK as i32; ```
There is no way of doing it directly in an easy and readable way like in C#. The thing is, Rust will use the best size for each enum according to its value.
```csharp // C# enum ErrorCode : ushort { None = 0, ConnectionLost = 100, }
// ... ushort errorCode = (ushort)ErrorCode.None; ```
```rust // Rust enum EnumA { // Each variant has 1 byte A = 1, B = 2 }
enum EnumB { // Each variant has 2 bytes A = 1000, B = 2 }
enum EnumC { // Each variant has 4 bytes A = 100000, B = 2 } ```
There isn't a direct equivalent in Rust, but there are many other alternatives, and one convenient way is importing and using the crate bitflags, which is a macro.
```csharp // C# [Flags] enum WeekDays { None = 0b00000000, // 0 Monday = 0b00000001, // 1 Tuesday = 0b00000010, // 2 Wednesday = 0b00000100, // 4 Thursday = 0b00001000, // 8 Friday = 0b00010000, // 16 Saturday = 0b00100000, // 32 Sunday = 0b01000000, // 64 Weekend = Saturday | Sunday }
// ... WeekDays today = WeekDays.Wednesday; bool isWeekend = today.HasFlag(WeekDays.Weekend); bool isWednesday = today.HasFlag(WeekDays.Wednesday); ```
```rust // Rust use bitflags::bitflags;
bitflags! { struct WeekDays: u8 { const MONDAY = 0b00000001; const TUESDAY = 0b00000010; const WEDNESDAY = 0b00000100; const THURSDAY = 0b00001000; const FRIDAY = 0b00010000; const SATURDAY = 0b00100000; const SUNDAY = 0b01000000; const WEEKEND = Self::SATURDAY.bits | Self::SUNDAY.bits; } }
// ... let today: WeekDays = WeekDays::WEDNESDAY; let isweekend: bool = today.intersects(WeekDays::WEEKEND); let iswednesday: bool = today.contains(WeekDays::WEDNESDAY); ```
There isn't something similar in C#. In Rust, a good approach to work with the associated values of each variant is using the keyword match and impl.
```rust // Rust enum IpAddr { V4(String), V6(String), }
impl IpAddr { fn tostring(&self) -> &String { match self { IpAddr::V4(ip) => ip, IpAddr::V6(ip) => ip, } } fn isipv4(&self) -> bool { match self { IpAddr::V4() => true, IpAddr::V6() => false, } } }
// ... let loopback: IpAddr = IpAddr::V4(String::from("127.0.0.1")); print!("Loopback: {}", loopback.tostring()); println!("Is IPv4? {}", loopback.isipv4()); ```
```rust // Rust enum CanvasCommand { Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
impl CanvasCommand { fn apply(&self) { match self { CanvasCommand::Move { x, y } => println!("Move to {}, {}", x, y), CanvasCommand::Write(text) => println!("Write {}", text), CanvasCommand::ChangeColor(r, g, b) => println!("Change color to {}, {}, {}", r, g, b), } } }
// ...
let drawing: Vec
for command in drawing { command.apply(); } ```