为什么在Rust中使用动态错误而不是枚举很常见?使用编译时变体有什么问题/不可能吗?

14

我在 Rust 中发现了这种趋势,即 Result 中的错误是以这种方式返回的:

fn do_something() -> Result<SomeType, Box<dyn std::error::Error>> {
    // ...
}

为什么错误是动态的?由于我来自C++背景并且更喜欢std::variant而非经典的多态(我相对较新于rust),我对动态分配很过敏,所以只有在必要时才使用它们。我也发现Rust的枚举很棒,因为其中包括变量。请问为什么没有将错误用作枚举是标准/首选/常见的呢?


动态错误是更好的选择,因为需要输入的内容更少。 - Boiethios
5
你可能正在看针对用户的应用程序,这些应用程序通常需要处理多种错误类型,而Box<dyn Error>是它们所有错误类型的共同点。但在库中使用这种方法绝不是我的建议。 - E net4
3
如果你还没有阅读 Rust 中的错误处理,强烈推荐这篇文章,作者 Andrew Gallant 对不同的方法进行了深入讲解。如果你喜欢,你可以保持强类型。 - Logan Reed
从@LoganReed发布的“Rust中的错误处理”链接中可以看到:“如果您正在编写一个快速且不太规范的程序,并且对于panic感到羞耻,那么您应该使用Box<Error>(或Box<Error + Send + Sync>)”。 - solstice333
1个回答

21

在应用程序代码中,这通常是出于方便而这样做的。将所有错误类型静态地知晓可能会成为维护的噩梦:您拥有一个不断扩大的可能错误类型枚举,其中大部分您永远不会尝试单独处理。这些错误类型会以某种方式污染距离实际发生错误的位置很远的类型签名。Box<dyn std::error::Error>保持事物非常干净,额外的分配通常不是问题,因为它只发生在错误情况下。

在库箱中比较罕见,但有些非常通用的代码可能无法知道所有可能的错误类型。当组合多个结果类型时,为错误使用类型参数会变得非常笨拙。一种可能的静态已知错误组合的复杂结构可以方便地折叠成单个类型:Box<dyn std::error::Error>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接