如何在Rust中匹配数据类型?

Das*_*h83 10 rust

我正在尝试匹配结构的通用字段的数据类型并做出相应的反应.我的总体想法是这样的(代码不编译):

struct Foo<T> {
    bar: T,
}

fn main() {
    let x = Foo::<String> {
        bar: "world".to_string(),
    };

    match x.bar {
        String => println!("It's a string!"),
        u32 => println!("It's a u32!"),
        _ => println!("Something else"),
    };

    println!("end of program!");
}
Run Code Online (Sandbox Code Playgroud)

来自的错误消息x:

warning: unreachable pattern
  --> src/main.rs:12:9
   |
11 |         String => println!("It's a string!"),
   |         ------ matches any value
12 |         u32 => println!("It's a u32!"),
   |         ^^^ unreachable pattern
   |
   = note: `#[warn(unreachable_patterns)]` on by default

warning: unreachable pattern
  --> src/main.rs:13:9
   |
11 |         String => println!("It's a string!"),
   |         ------ matches any value
12 |         u32 => println!("It's a u32!"),
13 |         _ => println!("Something else"),
   |         ^ unreachable pattern

warning: unused variable: `String`
  --> src/main.rs:11:9
   |
11 |         String => println!("It's a string!"),
   |         ^^^^^^ help: consider prefixing with an underscore: `_String`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `u32`
  --> src/main.rs:12:9
   |
12 |         u32 => println!("It's a u32!"),
   |         ^^^ help: consider prefixing with an underscore: `_u32`

warning: variable `String` should have a snake case name
  --> src/main.rs:11:9
   |
11 |         String => println!("It's a string!"),
   |         ^^^^^^ help: convert the identifier to snake case: `string`
   |
   = note: `#[warn(non_snake_case)]` on by default
Run Code Online (Sandbox Code Playgroud)

我想要的是x匹配第一个,并x匹配第二个.我实际上不确定我想做什么,但是什么会达到预期的效果呢?

Mat*_* M. 15

惯用解决方案

创建该约束的参数特性TFoo,实现任何特定的行为,因为这性状相关功能.

例:

trait PrintMe {
    fn print_me(&self);
}

impl PrintMe for String {
    fn print_me(&self) { println!("I am a string"); }
}

struct Foo<T: PrintMe> {
    bar: T
}

fn main() {
    // ...
    x.bar.print_me();
}
Run Code Online (Sandbox Code Playgroud)

这是一种原则性的通用编程,您可以准确地声明可能的通用参数的行为差异,因此毫无意外.


精确的解决方案

Rust确实可以查询类型:每种类型都有唯一的TypeId关联,并且您可以匹配TypeId一系列if检查.它很笨重.

fn print_me<T>(x: &Foo<T>) {
    if TypeId::of::<T>() == TypeId::of::<String>() {
        println!("I am a string");
    } else // ...
}
Run Code Online (Sandbox Code Playgroud)

但是请...不要那样做:)

  • +1 表示“不要那样做”,我只是指出 Rust *有 * `enum`,这是编写所有这些 `TypeId 的更好(更短、更清晰、惯用和编译时检查)的方式::of` 检查。 (2认同)
  • @trentcl:这取决于。“enum”用于封闭多态性,而“trait”用于开放多态性......如果这是有道理的。 (2认同)