, , . , , - .
class Disposable : IDisposable {
public void Dispose() {
Console.WriteLine("Disposed!");
}
}
IEnumerable<int> CreateEnumerable() {
int i = 0;
using (var d = new Disposable()) {
while (true) yield return ++i;
}
}
void UseEnumerable() {
foreach (int i in CreateEnumerable()) {
Console.WriteLine(i);
if (i == 10) break;
}
}
1 10 Disposed!
? . , UseEnumerable. foreach :
var e = CreateEnumerable().GetEnumerator();
try {
while (e.MoveNext()) {
int i = e.Current;
Console.WriteLine(i);
if (i == 10) break;
}
} finally {
e.Dispose();
}
( ), #, 8.8.4. , a foreach Dispose .
, using CreateEnumerable . , , :
IEnumerable<int> CreateEnumerable() {
int i = 0;
Disposable d = new Disposable();
try {
repeat:
i = i + 1;
yield return i;
goto repeat;
} finally {
d.Dispose();
}
}
10.14 . , . , # , # , , . , , , , , , .
class CreateEnumerable_Enumerator : IEnumerator<int> {
private int i;
private Disposable d;
private int current;
public int Current => current;
object IEnumerator.Current => current;
enum State { Before, Running, Suspended, After };
private State state = State.Before;
public bool MoveNext() {
switch (state) {
case State.Before: {
state = State.Running;
i = 0;
d = new Disposable();
i = i + 1;
current = i;
state = State.Suspended;
return true;
}
case State.Running: return false;
case State.Suspended: {
state = State.Running;
i = i + 1;
current = i;
state = State.Suspended;
return true;
}
case State.After: return false;
default: return false;
}
}
public void Dispose() {
switch (state) {
case State.Before: state = State.After; break;
case State.Running: break;
case State.Suspended: {
state = State.Running;
d.Dispose();
state = State.After;
}
break;
case State.After: return;
default: return;
}
}
public void Reset() { throw new NotImplementedException(); }
}
class CreateEnumerable_Enumerable : IEnumerable<int> {
public IEnumerator<int> GetEnumerator() {
return new CreateEnumerable_Enumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
IEnumerable<int> CreateEnumerable() {
return new CreateEnumerable_Enumerable();
}
, yield return yield break, " " . finally Dispose. , yield return. , finally finally, , . foreach ( , Dispose , finally), .
; , , .. " " .