maf*_*afu 5 .net c# ienumerable
在返回的方法中IEnumerable<>,我打开并循环遍历资源(例如,数据库行读取器).循环结束后,资源再次关闭.
但是,可能会发生呼叫者决定不完成枚举的情况.这使资源保持开放.
例:
IEnumerable<Foo> Bar ()
{
using (var r = OpenResource()) {
while (r.Read ()) {
yield return r;
}
}
}
// OK - this closes the resource again
foreach (var foo in Bar()) {
Console.WriteLine (foo);
}
// Not OK - resource stays open!
Console.WriteLine (Bar().First());
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?我可以轻松取消枚举,即告诉它跳过循环的其余部分,或者将其丢弃(将清理代码放入Dispose)?
我考虑过返回一个Func<Result, bool>如此用户可以让它返回,false如果他完成迭代.同样,也可以使用某种取消令牌.但这两种方法对我来说都很麻烦.
xan*_*tos 12
通常它是IEnumerator<>实现的IDisposable,如果你看一下你的定义,IEnumerator<>你会看到:
public interface IEnumerator<out T> : IDisposable, IEnumerator
Run Code Online (Sandbox Code Playgroud)
在foreach正确的语句Dispose()在IEnumerator<>从接收IEnumerable<>,因此:
IEnumerable<SomeClass> res = SomeQuery();
foreach (SomeClass sc in res)
{
if (something)
break;
}
Run Code Online (Sandbox Code Playgroud)
在离开foreach以任何方式(的break,一个例外,自然整理res),所述Dispose()的IEnumerator<>应被调用.见https://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx为的是如何一个例子foreach是实现(A try... finally...用Dispose()里面的finally)
请注意,C#将生成using用于yield函数内部的"正确"代码.例如,请参阅:http://goo.gl/Igzmiz
public IEnumerable<Foo> Bar()
{
using (var r = OpenResource())
{
while (r.Read ())
{
yield return new Foo();
}
}
}
Run Code Online (Sandbox Code Playgroud)
被转换为某种东西
void IDisposable.Dispose()
{
int num = this.<>1__state;
if (num == -3 || num == 1)
{
try
{
}
finally
{
this.<>m__Finally1();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所述Dispose()的方法IEnumerator<>将调用m__Finally1,将方法(IDisposable)this.<r>5__1.Dispose();(其中,5__1在r从返回OpenResource()).该m__Finally甚至被称为如果代码简单的"退出"的while (r.Read ()):
if (!this.<r>5__1.Read())
{
this.<>m__Finally1();
Run Code Online (Sandbox Code Playgroud)
和/或如果有例外.
catch
{
this.System.IDisposable.Dispose();
Run Code Online (Sandbox Code Playgroud)