将通用参数转换为特定类型

at5*_*321 1 generics casting rust

如果我有两个结构:

struct A {...}
struct B {...}
Run Code Online (Sandbox Code Playgroud)

fn f<T>(param: T)以及我通过传递对Aor的引用来调用的通用函数B,该函数中是否有一种方法可以具有类似这样的内容(伪代码):

if param is A {
    // do something with "param as A", like this:
    let a: A = (A) param;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在 Java、C# 等语言中,我会简单地检查一个对象是否是 的实例A,如果是,则将其强制转换A为上面的示例。我怎样才能在 Rust 中做类似的事情?我知道我可以将一些特定于类型的逻辑放入特征中,但我特别要求一种更简单、更直接的方法。

Sve*_*ach 5

您可以使用特征的特征对象来完成您所要求的操作Any,例如

use std::any::Any;

#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;

fn foo(param: &dyn Any) {
    if let Some(a) = param.downcast_ref::<A>() {
        dbg!(a);
    }
    if let Some(b) = param.downcast_ref::<B>() {
        dbg!(b);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,对于常见的用例,有更惯用、符合人体工程学和高效的解决方案。A您提到在您的问题中实现一个共同特征B,这是一种方法。另一种方法是定义一个枚举,其中包含您想要支持的所有类型的变体:

enum MyEnum {
    A(A),
    B(B),
}

fn bar(param: MyEnum) {
    match param {
        MyEnum::A(a) => { dbg!(a); },
        MyEnum::B(b) => { dbg!(b); },
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这里值得一提的是:(1) 由于额外的间接性,使用 `&amp;dyn Any` 会对性能产生不利影响;(2) Java 和 C# 默认使用装箱类型,这就是为什么它们不需要额外的努力就能做到这一点;(3) 依赖于运行时的类型检查会使你的抽象泄漏,并且通常表明你的抽象一开始就设计得很糟糕。你不能将 Rust 与 Java 或 C# 进行比较,因为它们是完全不同的野兽。 (5认同)