11

有没有一种通过一次性资源产生收益的适当方法?返回的对象是 IDisposable,但它正在迭代的元素是。

这是一个例子:

public static IEnumerable<T> Fetch(IEnumerable<Guid> ids)
{
    using (var client = new CouchbaseClient())
    {
        yield return ids.Select(s => s.ToString());
    }
}

现在,调用它不会释放using获得的资源。我知道我可以只返回一个 ToList 并立即将其全部返回,但是有没有办法“正确”处理这个问题,或者我是否必须在 IDisposable 资源上保留一个选项卡并在完成后手动处理它?

4

1 回答 1

7

简而言之,只要方法的调用者IEnumerator正确处理对象,您就不必担心它。

IEnumerator实现IDisposable,并且用于创建迭代器块的逻辑实际上足够聪明,可以在处理所有未执行的 finally 块时执行它。作为调用的结果创建了一个 finally 块using,这就是IDisposable资源被释放的地方。

因此,只要由此IEnumerator创建的对象IEnumerable被完全迭代(在这种情况下,最终MoveNext调用将到达using块的末尾并处置资源)或处置IDisposable客户端将被处置。

请注意,如果您担心代码的用户可能无法IEnumerator正确处理对象,那么最好不要使用带有惰性求值的迭代器块。如果您想确保即使调用者不“玩得很好”,也要急切地评估该方法(即获取您拥有的代码,将结果转储到一个列表中,然后返回该列表)。如果不释放资源的后果主要或完全与性能相关(不再释放一些内存,保持打开连接等),那么它可能不是问题,但如果永远持有锁是一个问题主要问题(即如果不释放可能导致死锁的锁定资源),那么惰性评估的优势可能不值得。

于 2012-11-22T01:46:25.107 回答