是否应该在匹配之前取消对枚举的引用?
Should a reference to an enum be dereferenced before it is matched?
作为 Rust 的新手,我偶然发现了两种在引用类型上 运行 和 match
显然有效的方法。
我定义了一个枚举:
enum Color {
Red,
Yellow,
Green,
Teal,
Blue,
Purple,
}
我想实现一个函数,该函数作用于此枚举实例的 &self
引用。
我可以看到两种写这样一个函数的方法:
impl Color {
// Approach #1: Match the reference, using references in each pattern
fn contains_red(&self) -> bool {
match self {
&Color::Red => true,
&Color::Yellow => true,
&Color::Purple => true,
_ => false,
}
}
// Approach #2: Dereference &self and match the patterns directly
fn contains_blue(&self) -> bool {
match *self {
Color::Blue => true,
Color::Teal => true,
Color::Purple => true,
_ => false,
}
}
}
我预计取消引用 &self
会被算作一个移动,如果我连续两次在同一实例上调用 color.contains_blue()
会导致错误,但这似乎不是案.
这些方法在功能上是否相同?如果我匹配更复杂的对象,其中一个会坏掉吗?
我个人更喜欢第二种。在我看来,它更好地传达了意图。
您无法移出不可变引用,因此您不必担心这种情况。
值得考虑的是,人们希望匹配工作 有点 类似于 (Partial
)Eq
,而这需要 &self
。换句话说,除非被迫,否则人们会期望它隐含地引用。通过一些实验很容易证实这一点。
值得注意的是 *self
不是 移动 - 它是对内存位置的引用。 It is thus an lvalue. 因此,
When the head expression is an lvalue, the match does not allocate a temporary location (however, a by-value binding may copy or move from the lvalue).
https://doc.rust-lang.org/stable/reference/expressions/match-expr.html
如果没有分配临时位置,则无法进行移动。因此,行为得到保证。正如附带说明的那样,内部数据仍然可以从解构模式中移出,这会导致问题。然而,无论您是在 self
还是 *self
.
上进行匹配,这都是正确的
使用 *self
似乎是一种非正式的习语,应该是首选。
从 Rust 1.26 开始,惯用的解决方案是 两者都不;您不必取消引用值 或 将 &
添加到模式:
fn contains_blue(&self) -> bool {
match self {
Color::Blue => true,
Color::Teal => true,
Color::Purple => true,
_ => false,
}
}
这要归功于改进的匹配人体工程学。
您也可以在这种情况下使用模式交替:
match self {
Color::Blue | Color::Teal | Color::Purple => true,
_ => false,
}
作为 Rust 的新手,我偶然发现了两种在引用类型上 运行 和 match
显然有效的方法。
我定义了一个枚举:
enum Color {
Red,
Yellow,
Green,
Teal,
Blue,
Purple,
}
我想实现一个函数,该函数作用于此枚举实例的 &self
引用。
我可以看到两种写这样一个函数的方法:
impl Color {
// Approach #1: Match the reference, using references in each pattern
fn contains_red(&self) -> bool {
match self {
&Color::Red => true,
&Color::Yellow => true,
&Color::Purple => true,
_ => false,
}
}
// Approach #2: Dereference &self and match the patterns directly
fn contains_blue(&self) -> bool {
match *self {
Color::Blue => true,
Color::Teal => true,
Color::Purple => true,
_ => false,
}
}
}
我预计取消引用 &self
会被算作一个移动,如果我连续两次在同一实例上调用 color.contains_blue()
会导致错误,但这似乎不是案.
这些方法在功能上是否相同?如果我匹配更复杂的对象,其中一个会坏掉吗?
我个人更喜欢第二种。在我看来,它更好地传达了意图。
您无法移出不可变引用,因此您不必担心这种情况。
值得考虑的是,人们希望匹配工作 有点 类似于 (Partial
)Eq
,而这需要 &self
。换句话说,除非被迫,否则人们会期望它隐含地引用。通过一些实验很容易证实这一点。
值得注意的是 *self
不是 移动 - 它是对内存位置的引用。 It is thus an lvalue. 因此,
When the head expression is an lvalue, the match does not allocate a temporary location (however, a by-value binding may copy or move from the lvalue).
https://doc.rust-lang.org/stable/reference/expressions/match-expr.html
如果没有分配临时位置,则无法进行移动。因此,行为得到保证。正如附带说明的那样,内部数据仍然可以从解构模式中移出,这会导致问题。然而,无论您是在 self
还是 *self
.
使用 *self
似乎是一种非正式的习语,应该是首选。
从 Rust 1.26 开始,惯用的解决方案是 两者都不;您不必取消引用值 或 将 &
添加到模式:
fn contains_blue(&self) -> bool {
match self {
Color::Blue => true,
Color::Teal => true,
Color::Purple => true,
_ => false,
}
}
这要归功于改进的匹配人体工程学。
您也可以在这种情况下使用模式交替:
match self {
Color::Blue | Color::Teal | Color::Purple => true,
_ => false,
}