泛型和内联(我不知道它们叫什么)类型定义有什么区别?
示例代码:
fn main() {
c(|| {
println!("hello");
})
}
fn a<F>(f: F)
where
F: FnOnce() + Send + 'static,
{
f();
}
fn b<F: FnOnce() + Send + 'static>(f: F) {
f();
}
fn c(f: FnOnce() + Send + 'static) {
f();
}
Run Code Online (Sandbox Code Playgroud)
这里a工作b正常但c给出错误:“特征对象必须包含dyn关键字”
如果我这次添加关键字,则会出现另一个错误:“编译时无法知道dyn类型值的大小”(dyn FnOnce() + Send + 'static)
那么你能解释一下 in 中的类型声明有何c不同吗?
a和b完全等价。c 过去是允许的(但意味着不同的东西),但他们添加了一个关键字来消除歧义。使用新语法的等效内容是
fn c(f: impl FnOnce() + Send + 'static)
{
f();
}
Run Code Online (Sandbox Code Playgroud)
这与aand相同b,只是不允许调用者显式指定类型注释,因此a::<SomeType>(x)允许但c::<SomeType>(x)禁止。这通常并不重要,FnOnce因为该类型很可能是 lambda 类型,无论如何都无法拼写出来。
编译器建议放入的内容会dyn改变含义。
fn c(f: &dyn FnOnce() + Send + 'static)
{
f();
}
Run Code Online (Sandbox Code Playgroud)
这不声明通用函数。它声明了一个采用特征对象的函数。在泛型函数的情况下,泛型的类型在编译时就已知,这可以实现更好的优化(通常,FnOnce作为 lambda 的参数可以完全内联)。当编译时类型未知时dyn使用,并且更直接地模拟具有实现隐藏的 Java 风格。interface
(我还必须添加 a,&因为类型未调整大小并且不能是函数参数。如果需要所有权,dyn您也可以将其放在 a 中)Box<dyn ...>
您应该使用泛型而不是dyn尽可能使用泛型。a在、b和的三个实现中c,除了能够在a和 的情况下指定类型参数之外,它们几乎都是等效的b。对于FnOnceand company,我会使用,c因为我们几乎不想指定参数。对于其他特征(FromIterator这是我们经常想要指定类型的一个大特征),我可能会喜欢a或b;这两者中的哪一个取决于您的偏好。这两者是完全等价的。