使用IDisposable资源产生

Jes*_*ess 10 c# yield-return

是否有通过一次性资源获得收益的正确方法?返回的对象是IDisposable,但它迭代的元素是.

这是一个例子:

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

现在,调用它不会处理using获得的资源.我知道我可以只是一个ToList并立即返回它,但有没有办法正确地处理它,或者我必须在IDisposable资源上保留一个标签并在我完成后手动处理它?

Ser*_*rvy 7

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

IEnumerator实现IDisposable,并且创建迭代器块时使用的逻辑实际上足够智能,可以在处理时执行所有未执行的finally块.作为using调用的结果创建finally块,这是IDisposable资源被放置的位置.

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

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