rust - 如何在方法实现中从枚举中的字符串返回 &str?

标签 rust borrow-checker

我想返回城市/城镇/村庄的名称作为对 str 的引用。我可以在实现中指定生命周期,但也为枚举指定它会导致错误,因为它没有声明引用。

enum CityType {
    City { name: String /* ... */ },
    Town { name: String /* ... */ },
    Village { name: String /* ... */ },
}

impl CityType {
    fn name(self) -> &str {
        match self {
            CityType::City { name } => &name,
            CityType::Town { name, .. } => &name,
            CityType::Village { name } => &name,
        }
    }
}

playground

最佳答案

如果只是想返回一个城市名而不消费丢失对象,应该这样写:

enum CityType {
    City { name: String },
    Town { name: String },
    Village { name: String },
}

impl CityType {
    fn name(&self) -> &str {
        match *self {
            CityType::City { ref name } => name,
            CityType::Town { ref name, .. } => name,
            CityType::Village { ref name } => name,
        }
    }
}

fn main() {
    let city = CityType::City { name: "NY".to_owned() };
    println!("Name of the city: {}", city.name());
}

解释:

  1. 首先,您的方法的签名指定您使用对象:

    fn name(self) -> &str {
    

    调用这样的方法后,您将无法再使用该实例。如果你想读取一个字符串,你应该接受一个引用:

    fn name(&self) -> &str {
    

    这导致了另一个问题

  2. match 应该在不移动对象的情况下工作,所以这里是 *:

    match *self {
    
  3. 你不应该从枚举的数据中移出,所以 ref 关键字有帮助

    CityType::City { ref name } => name,
    

    这个关键字表示我们必须使用带有值引用的模式匹配。

  4. main 中,您传递了一个 &str,但您的枚举中的项目是 String,因此这会导致类型不兼容的错误。通过在字符串引用上调用 .to_owned() 方法,您可以从中创建一个新的 String 对象:

    let city = CityType::City { name: "NY".to_owned() };
    

对于您的评论:

The issue is more general: how to return ref to a String which has no lifetime specifier as it lives as long as the enum does.

在 Rust 中,你不能没有生命周期的引用。绝不。在某些情况下,编译器可以为您推断出生命周期,但在某些情况下,它会错误地或不符合您的预期。在这种情况下,例如:

fn name(&self) -> &str {

存在生命周期,编译器将其视为如下:

fn name<'a>(&'a self) -> &'a str {

您的引用绑定(bind)到相同的生命周期并且可以使用它们。

关于rust - 如何在方法实现中从枚举中的字符串返回 &str?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47868272/

相关文章:

http - 带有Rust的AWS Lambda的reqwest段错误

rust - 你如何访问 Rust 中的枚举值?

reference - 当结构及其成员具有不同的生命周期时理解 Rust 中的引用

rust - 递归类型-生命周期问题

rust - 方法返回具有相同生命周期的结构迭代器的生命周期

rust - 在 actix-web 路由处理程序中使用预先计算的大对象

rust - 如何从 Rust 应用程序连接到 Docker 容器中的 SurrealDB?

rust - 当 Rust 中的指针类型不同时如何生成编译错误?

rust - 是否可以借用结构的一部分作为可变部分而其他部分作为不可变部分?

rust - 如何在不冒犯借用检查器的情况下进行计算状态转换?