Число в enum

На РСДН-е задали довольно интересный вопрос на тему того, почему для преобразования из числа в значение из enum-а необходимо городить следующую конструкцию:

FromPrimitive::from_int(x).unwrap();

вместо того что бы писать x as int.

Прежде всего надо учитывать, что приведение типов с помощью FromPrimitive создавалось с оглядкой на стандартные перечисления из языка Си. При этом, значения входящие в перечисление в Си, как впрочем и в Rust, не должны идти последовательно, одно за другим, т.е. часть значений может отсутствовать. В качестве примера возьмем такой код:

use std::num::FromPrimitive;
use std::int;

#[deriving(FromPrimitive)]  // (1)
enum MyType {
    Val1 = 0,
    Val2 = 1,
    Val3 = 10
}

fn main() {
    let val1: Option<MyType> = FromPrimitive::from_int(1);     // (2)
    let val2: Option<MyType> = FromPrimitive::from_int(2);     // (3)

    println!("{:?}, {:?}", val1, val2);
}

Где объявляем возможность приведения целочисленных типов к TestData при помощи FromPrimitive 1 и делаем две конверсии, одну для существующего в перечислении значения 1 2, а вторую для не существующего значения 2 3. В консоли у нас окажется, как и ожидалось:

Some(Val2), None

А теперь к примеру с x as MyType. В таком примере предполагается, что все конверсии должны проходить успешно. Но что делать, если конверсия не удалась и нам вернулся None, как в примере выше 3? Попытка “добыть” значение из None приведет к печальным последствиям:

val2.unwrap();
task '<main>' failed at 'called `Option::unwrap()` on a `None` value'

В то время как гарантировать преобразование от числового значения к нашему типу мы не можем.

6 Comments Число в enum

  1. KonstantinK

    после использования .NET, такое поведение достаточно странное и неожиданное

    Reply
      1. KonstantinK

        падением.
        в dotnet’е ведь можно как угодно “целое enum” переводить без исключений

        Reply
          1. Alexander Stavonin

            .NET не дает жесткой гарантии что тип преобразовался корректно, в то время как Rust дает гарантии по допустимости всех преобразований на этапе компиляции. Вот и вся разница

Leave a Reply