2009-10-02 5 views
7

Есть ли какой-либо способ в блоке итератора C#, чтобы обеспечить блок кода, который будет запускаться, когда конец foreach (естественно, из-за того, что он разбит), скажем, чтобы очистить ресурсы?«И окончательно» Блок в итераторах

Лучшее, что я придумал, это использовать конструкцию using, которая хороша, но для очистки требуется класс IDisposable. Например:

public static IEnumerable<string> ReadLines(this Stream stream) 
    { 
     using (StreamReader rdr = new StreamReader(stream)) 
     { 
      string txt = rdr.ReadLine(); 
      while (txt != null) 
      { 
       yield return txt; 
       txt = rdr.ReadLine(); 
      } 
      rdr.Close(); 
     } 
    } 

ответ

5

try/finally работает отлично, до тех пор, как вызывающий абонент с помощью foreach или вручную вызывает Dispose на IEnumerator<T>. Если честно, если нужно очистить ресурсы, то заявление using, вероятно, будет лучшим способом сделать это в любом случае - если вы используете ресурс, который нуждается в очистке, но не реализует IDisposable, это само по себе :)

Существуют определенные ограничения на то, что вы можете сделать в блоках итератора, как explained on Eric Lippert's blog, но в большинстве случаев все это очень хорошо.

Вы можете найти my article about iterator block implementation интересным с точки зрения перевода finally.

0

try/finally работает в этом случае.

public static IEnumerable<string> ReadLines(this Stream stream) 
{ 
    StreamReader rdr = new StreamReader(stream); 

    try 
    { 
     string txt = rdr.ReadLine(); 
     while (txt != null) 
     { 
      yield return txt; 
      txt = rdr.ReadLine(); 
     } 
     rdr.Close(); 
    } 
    finally 
    { 
     rdr.Dispose(); 
    } 
} 
Смежные вопросы