gpt4 book ai didi

c# - IEnumerable 的异常处理问题,它依赖于惰性

转载 作者:太空狗 更新时间:2023-10-29 20:00:47 25 4
gpt4 key购买 nike

我曾经用 IEnumerable<T> 创建接口(interface)作为返回类型,每当我想指定一个特定的输出是只读的。我喜欢它,因为它极简主义,隐藏了实现细节并将被调用者与调用者分离。

但最近我的一位同事认为 IEnumerable<T>应该保留用于仅涉及惰性评估的场景,否则对于调用方方法来说不清楚,异常处理应该发生在哪里 - 围绕方法调用或围绕迭代。然后对于具有只读输出的急切评估案例,我应该使用 ReadOnlyCollection .

对我来说听起来很合理,但您会推荐什么?您是否同意 IEnumerable 的惯例?或者是否有更好的方法来围绕 IEnumerable 进行异常处理?

为了防止我的问题不清楚,我制作了一个示例类来说明问题。这里的两个方法具有完全相同的签名,但它们需要不同的异常处理:

public class EvilEnumerable
{
IEnumerable<int> Throw()
{
throw new ArgumentException();
}

IEnumerable<int> LazyThrow()
{
foreach (var item in Throw())
{
yield return item;
}
}

public void Run()
{
try
{
Throw();
}
catch (ArgumentException)
{
Console.WriteLine("immediate throw");
}

try
{
LazyThrow();
}
catch (ArgumentException)
{
Console.WriteLine("No exception is thrown.");
}

try
{
foreach (var item in LazyThrow())
{
//do smth
}
}
catch (ArgumentException)
{
Console.WriteLine("lazy throw");
}
}
}

更新 1. 问题不仅限于 ArgumentException。它是关于制作友好类接口(interface)的最佳实践,告诉您它们是否返回惰性评估结果,因为这会影响异常处理方法。

最佳答案

这里真正的问题是延迟执行。在参数检查的情况下,您可以通过添加第二种方法来做到这一点:

IEnumerable<int> LazyThrow() {
// TODO: check args, throwing exception
return LazyThrowImpl();
}
IEnumerable<int> LazyThrowImpl() {
// TODO: lazy code using yield
}

异常发生;即使对于非延迟结果(例如 List<T>),您也会遇到错误(可能是在您迭代时另一个线程调整了列表)。上述方法让您尽可能提前做,以减少 yield 的意外副作用。和延迟执行。

关于c# - IEnumerable<T> 的异常处理问题,它依赖于惰性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1738820/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com