2014-09-13 5 views
2

Я столкнулся с приведенным ниже примером кода в документации MSDN, демонстрируя использование класса System.IO.StreamReader для чтения текста UTF-8 из объекта System.IO.FileStream. Два вложенных оператора using поразили меня как избыточное - конечно, вызов Dispose() на одном из объектов делает трюк и правильно освобождает дескриптор файла? (Источник: http://msdn.microsoft.com/en-us/library/yhfzs7at.aspx)C# - вложенные операторы с избыточностью?

using (FileStream fs = new FileStream(path, FileMode.Open)) 
{ 
    using (StreamReader sr = new StreamReader(fs)) 
    { 

     while (sr.Peek() >= 0) 
     { 
      Console.WriteLine(sr.ReadLine()); 
     } 
    } 
} 

Не было бы проще, и в равной степени правильно, чтобы переписать этот код следующим образом?

using (FileStream fs = new FileStream(path, FileMode.Open)) 
{ 
    StreamReader sr = new StreamReader(fs); 

    while (sr.Peek() >= 0) 
    { 
     Console.WriteLine(sr.ReadLine()); 
    } 
} 
+1

Я считаю, что неплохо распоряжаться всем, что реализует 'IDisposable'. – Tommi

+0

Аналогичный вопрос с хорошими ответами: http://stackoverflow.com/q/9949377/361684 – gilly3

ответ

2

Согласно документации, The StreamReader object calls Dispose() on the provided Stream object when StreamReader.Dispose is called. Это означает, что usingStreamReader гарантирует удаление базового Stream. Он не выполняется наоборот: убрать только Streamне хватает - StreamReader может выделять другие собственные ресурсы. Таким образом, второй пример неверен.

(using только StreamReader не покрывает случай, когда StreamReader конструктор может бросить. Для того, чтобы покрыть этот случай, было бы необходимо оба using «s. Так как он бросает только не считываемый или null потоков, это не может быть однако.)

В общем, вы всегда должны распоряжаться каждым одноразовым объектом. Это часть договора IDisposable, что не помешает многократно удалять объект, и накладные расходы при этом низки.

+1

Ваша цитата верна, но не относится к образцу второго кода. –

+0

@HenkHolterman Я также говорю, что второй пример по этой причине неверен. –

+0

Не очень явный. –

2

Второй образец просто ошибочен в принципе.

Это не будет течь ничего, кроме того, что полагается на знание того, что StreamReader не имеет собственных ресурсов и на самом деле не нуждается в утилизации, даже если он IDisposable.

Один using(){} вокруг StreamReader был бы более или менее правильно здесь, на основе документально (и критике) особенность, что читатель закроет поток.

Лучшей практикой здесь является использование 2 с использованием статусов. Обратите внимание, что они очень дешевы, и вы просто хотите, чтобы код был последовательным.

+0

Обратите внимание, что 'StreamReader' также предоставляет возможность сказать * не закрывать базовый поток *. Также одиночный оператор using только в 'StreamReader' является проблемой при вызове конструктора,' FileStream' не будет закрыт. –

+0

@SriramSakthivel - с Fx 4.5, да. Но здесь не используется котор. –

+0

Верно, я добавляю, что есть возможность оставить поток открытым. Btw Я отредактировал мой предыдущий комментарий, чтобы указать, что однопользовательское заявление вокруг StreamReader будет опасным. –

Смежные вопросы