Arc<T>
会自动解除引用T
(通过Deref
特征),因此您可以在{{1}类型的值上调用T
方法}}
但有没有办法允许匹配Arc<T>
- 类型?
这是一个简单的例子:
Option
编译错误是:
use std::sync::Arc;
fn main() {
let foo: Arc<Option<String>> = Arc::new(Some("hello".to_string()));
if foo.is_some() {
println!("{}", foo.unwrap());
}
match foo {
Some(hello) => {
println!("{}", hello);
}
None => {}
}
}
答案 0 :(得分:6)
不,您无法匹配Option
内的Arc
。要在模式匹配中使用类型,必须可以使用该类型的实现,但Arc
的实现不公开。
在某些情况下,您可以执行某种转换,以便能够匹配参考。
例如,由于Arc<T>
实现了Deref
,您可以使用*
运算符通过Arc<T>
取消引用基础T
。由于这种匹配有some ergonomic syntax,因此您可以在Option
内对值进行引用,而无需获取所有权:
match *foo {
Some(ref hello) => {
println!("{}", hello);
}
None => {}
}
您还可以使用Option::as_ref
将&Option<T>
(automatically dereferenced从Arc<T>
转换为Deref
)转换为Option<&T>
:
match Option::as_ref(&foo) {
Some(hello) => {
println!("{}", hello);
}
None => {}
}
不幸的是,您不能只调用.as_ref()
,因为特征方法AsRef::as_ref
优先。
在这两种情况下,如果您只关心其中一个匹配组,那么使用if let
会更加惯用:
if let Some(ref hello) = *foo {
println!("{}", hello);
}
答案 1 :(得分:3)
第一个println
通过了编译器的早期阶段,但它在稍后阶段被借用检查程序标记。第二个println
更容易解决。
use std::sync::Arc;
fn main() {
let foo: Arc<Option<String>> = Arc::new(Some("hello".to_string()));
if foo.is_some() {
let f1: &Option<String> = foo.as_ref();
let f2: Option<&String> = f1.as_ref();
let f3: &String = f2.unwrap();
println!("{}", f3);
println!("{}", foo.as_ref().as_ref().unwrap())
}
match *foo {
Some(ref hello) => {
println!("{}", hello);
}
None => {}
}
}
第一个println
令人困惑地使用了两个as_ref()
方法调用。第一个as_ref
对Arc
采取行动,类型为签名Fn(&Arc<Option<String>>) -> &Option<String>
。第二个作用于Option
,类型为签名Fn(&Option<String>) -> Option<&String>