Worum geht es bei diesem Fragezeichenoperator?

Antworten:

133

Wie Sie vielleicht bemerkt haben, hat Rust keine Ausnahmen. Es gibt Panik, aber ihre Funktionalität ist eingeschränkt (sie können keine strukturierten Informationen enthalten) und von ihrer Verwendung zur Fehlerbehandlung wird abgeraten (sie sind für nicht behebbare Fehler gedacht).

In Rust wird die Fehlerbehandlung verwendet Result. Ein typisches Beispiel wäre:

fn halves_if_even(i: i32) -> Result<i32, Error> {
    if i % 2 == 0 {
        Ok(i / 2)
    } else {
        Err(/* something */)
    }
}

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = match halves_if_even(i) {
        Ok(i) => i,
        Err(e) => return Err(e),
    };

    // use `i`
}

Das ist großartig, weil:

  • Wenn Sie den Code schreiben, können Sie nicht versehentlich vergessen, sich mit dem Fehler zu befassen.
  • Wenn Sie den Code lesen, können Sie sofort erkennen, dass hier ein Fehlerpotential besteht.

Es ist jedoch weniger als ideal, da es sehr ausführlich ist. Hier kommt der Fragezeichenoperator ins Spiel ?.

Das Obige kann wie folgt umgeschrieben werden:

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = halves_if_even(i)?;

    // use `i`
}

das ist viel prägnanter.

Was ?hier geschieht, entspricht der matchobigen Aussage. Kurz gesagt: Es entpackt das Resultif OK und gibt den Fehler zurück, wenn nicht.

Es ist ein bisschen magisch, aber die Fehlerbehandlung erfordert etwas Magie, um das Boilerplate zu reduzieren, und im Gegensatz zu Ausnahmen ist sofort ersichtlich, welche Funktionsaufrufe fehlerhaft sein können oder nicht: diejenigen, die mit geschmückt sind ?.

Ein Beispiel für die Magie ist, dass dies auch funktioniert für Option:

// Assume
// fn halves_if_even(i: i32) -> Option<i32>

fn do_the_thing(i: i32) -> Option<i32> {
    let i = halves_if_even(i)?;

    // use `i`
}

Dies wird durch das (instabile) TryMerkmal angetrieben .

Siehe auch:

Matthieu M.
quelle
5
Es wäre schön, wenn Sie Ihre Antwort ein wenig erweitern könnten, z. B. diskutieren, dass der Rückgabetyp der Funktion mit dem Typ übereinstimmen muss, den Sie "auspacken" möchten, z . B. Resultoder Option.
Gelb
@hellow Ich denke, das wäre insgesamt eine neue Frage
Paul Razvan Berg