Rust для разработчиков C#: перечисления
Эта статья предназначена для разработчиков, которые уже знают, как разрабатывать программное обеспечение с помощью C#, чтобы показать, как перечисления работают в Rust, и исследовать альтернативы для выполнения тех же действий, которые мы привыкли делать в C#, а также новые возможности, предлагаемые в Ржавчина.
перечисления
Если вы хотите узнать больше о перечислениях, пожалуйста, прочитайте официальную документацию.
Простые перечисления
Основное отличие заключается в том, как мы вызываем перечисление для его использования.
// C# enum Country { Brazil, England, UnitedStates } // ... Country country = Country.Brazil; // Rust enum Country { Brazil, England, UnitedStates } // ... let country: Country = Country::Brazil;
Перечисления со связанными фиксированными значениями
Почти никакой разницы между C# и Rust.
// C# enum HttpStatus { OK = 200, NotFound = 404 } // ... HttpStatus status = HttpStatus.OK; int statusCode = (int)HttpStatus.OK; // Rust enum HttpStatus { OK = 200, NotFound = 404, } // ... let status: HttpStatus = HttpStatus::OK; let statusCode: i32 = HttpStatus::OK as i32;
Перечисления с пользовательскими типами
Невозможно сделать это напрямую простым и читаемым способом, как в C#. Дело в том, что Rust будет использовать лучший размер для каждого перечисления в соответствии с его значением.
// C# enum ErrorCode : ushort { None = 0, ConnectionLost = 100, } // ... ushort errorCode = (ushort)ErrorCode.None; // 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 }
Перечисления как битовые флаги
В Rust нет прямого эквивалента, но есть много других альтернатив, и один из удобных способов — это импорт и использование крейта bitflags, который представляет собой макрос.
// C# [Flags] enum WeekDays { None = 0b_0000_0000, // 0 Monday = 0b_0000_0001, // 1 Tuesday = 0b_0000_0010, // 2 Wednesday = 0b_0000_0100, // 4 Thursday = 0b_0000_1000, // 8 Friday = 0b_0001_0000, // 16 Saturday = 0b_0010_0000, // 32 Sunday = 0b_0100_0000, // 64 Weekend = Saturday | Sunday } // ... WeekDays today = WeekDays.Wednesday; bool isWeekend = today.HasFlag(WeekDays.Weekend); bool isWednesday = today.HasFlag(WeekDays.Wednesday); // 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 is_weekend: bool = today.intersects(WeekDays::WEEKEND); let is_wednesday: bool = today.contains(WeekDays::WEDNESDAY);
Перечисления со связанными неизвестными значениями, но известными типами
Ничего подобного в C# нет. В Rust хорошим подходом к работе со связанными значениями каждого варианта является использование ключевых слов match и impl.
// Rust enum IpAddr { V4(String), V6(String), } impl IpAddr { fn to_string(&self) -> &String { match self { IpAddr::V4(ip) => ip, IpAddr::V6(ip) => ip, } } fn is_ipv4(&self) -> bool { match self { IpAddr::V4(_) => true, IpAddr::V6(_) => false, } } } // ... let loopback: IpAddr = IpAddr::V4(String::from("127.0.0.1")); print!("Loopback: {}", loopback.to_string()); println!("Is IPv4? {}", loopback.is_ipv4()); // 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<CanvasCommand> = vec![ CanvasCommand::Move { x: 10, y: 10 }, CanvasCommand::Write(String::from("Hello")), CanvasCommand::Move { x: 20, y: 20 }, CanvasCommand::Write(String::from("World")), CanvasCommand::ChangeColor(0, 0, 0), ]; for command in drawing { command.apply(); }