## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# if let

在某些情况下，使用 `match` 匹配枚举可能会显得繁琐。例如：

    #![allow(unused)]
    fn main() {
    // 创建 `Option<i32>` 类型的 `optional`
    let optional = Some(7);

    match optional {
        Some(i) => println!("这是一个很长的字符串，其中包含 `{:?}`", i),
        _ => {},
        // ^ 这是必需的，因为 `match` 要求穷举所有情况。
        // 是不是觉得有些浪费空间？
    };

    }

对于这种情况，`if let` 更加简洁，而且还允许指定各种失败时的处理选项：

    fn main() {
        // 以下都是 `Option<i32>` 类型
        let number = Some(7);
        let letter: Option<i32> = None;
        let emoticon: Option<i32> = None;

        // `if let` 结构的含义是：如果 `let` 能将 `number` 解构为
        // `Some(i)`，则执行代码块（`{}`）。
        if let Some(i) = number {
            println!("匹配到 {:?}！", i);
        }

        // 如果需要指定匹配失败的情况，可以使用 else：
        if let Some(i) = letter {
            println!("匹配到 {:?}！", i);
        } else {
            // 解构失败。转到失败处理的情况。
            println!("没有匹配到数字。那就用一个字母吧！");
        }

        // 提供一个修改后的失败条件。
        let i_like_letters = false;

        if let Some(i) = emoticon {
            println!("匹配到 {:?}！", i);
        // 解构失败。评估 `else if` 条件，看是否应该执行替代的失败分支：
        } else if i_like_letters {
            println!("没有匹配到数字。那就用一个字母吧！");
        } else {
            // 条件判断为假。这个分支是默认情况：
            println!("我不喜欢字母。那就用个表情符号吧 :)！");
        }
    }

同样地，`if let` 可以用来匹配任何枚举值：

    // 我们的示例枚举
    enum Foo {
        Bar,
        Baz,
        Qux(u32)
    }

    fn main() {
        // 创建示例变量
        let a = Foo::Bar;
        let b = Foo::Baz;
        let c = Foo::Qux(100);

        // 变量 a 匹配 Foo::Bar
        if let Foo::Bar = a {
            println!("a 是 foobar");
        }

        // 变量 b 不匹配 Foo::Bar
        // 所以这里不会打印任何内容
        if let Foo::Bar = b {
            println!("b 是 foobar");
        }

        // 变量 c 匹配 Foo::Qux，它包含一个值
        // 类似于前面例子中的 Some()
        if let Foo::Qux(value) = c {
            println!("c 是 {}", value);
        }

        // `if let` 也可以进行绑定
        if let Foo::Qux(value @ 100) = c {
            println!("c 是一百");
        }
    }

`if let` 的另一个优点是它允许我们匹配非参数化的枚举变体。即使在枚举没有实现或派生 `PartialEq` 的情况下也是如此。在这种情况下，`if Foo::Bar == a` 将无法编译，因为枚举的实例无法进行相等比较，但 `if let` 仍然可以正常工作。

想要挑战一下吗？请修改以下示例，使用 `if let`：

    // 这个枚举故意既不实现也不派生 PartialEq。
    // 这就是为什么下面比较 Foo::Bar == a 会失败。
    enum Foo {Bar}

    fn main() {
        let a = Foo::Bar;

        // 变量 a 匹配 Foo::Bar
        if Foo::Bar == a {
        // ^-- 这会导致编译时错误。请改用 `if let`。
            println!("a 是 foobar");
        }
    }

### 另请参阅：

`枚举`、`Option` 和 RFC