Такие классы, как Stream
, StreamReader
и StreamWriter
т. Д. Реализует IDisposable
интерфейс. Это означает, что мы можем вызывать Dispose()
метод для объектов этих классов. Они также определили public
метод с именем Close()
. Теперь это смущает меня, что я должен назвать, как только я закончу с объектами? Что если я позвоню обоим?
Мой текущий код такой:
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
using (StreamWriter writer = new StreamWriter(filename))
{
int chunkSize = 1024;
while (!reader.EndOfStream)
{
char[] buffer = new char[chunkSize];
int count = reader.Read(buffer, 0, chunkSize);
if (count != 0)
{
writer.Write(buffer, 0, count);
}
}
writer.Close();
}
reader.Close();
}
}
Как видите, я написал using()
конструкции, которые автоматически вызывают Dispose()
метод для каждого объекта. Но я также называю Close()
методы. Это правильно?
Пожалуйста, предложите мне лучшие практики при использовании потоковых объектов. :-)
MSDN пример не использует using()
конструкции, а вызов Close()
метода:
Это хорошо?
using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { }
. Я имею в виду, как это, где вы можете переопределить тип:using (MemoryStream ms = new MemoryStream()) using (FileStream fs = File.OpenRead("c:\\file.txt")) { }
Ответы:
Быстрый переход в Reflector.NET показывает, что
Close()
метод onStreamWriter
:И
StreamReader
это:Dispose(bool disposing)
Переопределение вStreamReader
IS:StreamWriter
Метод подобен.Итак, читая код, становится ясно, что вы можете вызывать
Close()
&Dispose()
в потоках так часто, как вам нравится, и в любом порядке. Это никак не изменит поведение.Так что сводится к тому, является ли она более читаемой для использования
Dispose()
,Close()
и / илиusing ( ... ) { ... }
.Мое личное предпочтение заключается в том, что
using ( ... ) { ... }
всегда следует использовать, когда это возможно, так как это помогает вам «не бегать с ножницами».Но, хотя это помогает правильности, это уменьшает читабельность. В C # у нас уже есть множество закрывающих фигурных скобок, так как же мы узнаем, какая из них фактически выполняет закрытие в потоке?
Поэтому я думаю, что лучше всего сделать это:
Это не влияет на поведение кода, но способствует удобочитаемости.
источник
Close()
вызовом. Если кто-то менее опытный смотрит на код и не знает о нем,using
он будет: 1) искать его и изучать , или 2) слепо добавлятьClose()
вручную. Если он выберет 2), возможно, какой-то другой разработчик увидит избыточностьClose()
и вместо того, чтобы «посмеиваться», проинструктирует менее опытного разработчика. Я не за то, чтобы усложнять жизнь неопытным разработчикам, но я за то, чтобы превратить их в опытных разработчиков.Нет, вы не должны вызывать эти методы вручную. В конце
using
блокаDispose()
автоматически вызывается метод, который позаботится об освобождении неуправляемых ресурсов (по крайней мере для стандартных классов .NET BCL, таких как потоки, устройства чтения / записи и т. Д.). Таким образом, вы также можете написать свой код следующим образом:Close()
Метод вызываетDispose()
.источник
using
первым,responseStream
поскольку он обернут,reader
что обеспечит его закрытие при утилизации читателя. +1 тем не менееThe Close method calls Dispose.
... и в остальной части вашего поста, вы подразумеваете, чтоDispose()
будет звонитьClose()
, я не должен вызывать последний вручную. Вы говорите, что они называют друг друга?using
блок. Я реализую класс, который пишет время от времени и, следовательно, не может.using
(или, опять же, перейти к шаблону Dispose).В документации сказано, что эти два метода эквивалентны:
Итак, оба они одинаково действительны:
Лично я бы придерживался первого варианта, так как он содержит меньше «шума».
источник
Во многих классах, которые поддерживают оба
Close()
иDispose()
методы, два вызова будут эквивалентны. Однако в некоторых классах можно повторно открыть объект, который был закрыт. Некоторые такие классы могут поддерживать некоторые ресурсы после закрытия, чтобы разрешить повторное открытие; другие могут не поддерживать какие-либо ресурсыClose()
, но могут установить флаг,Dispose()
чтобы явно запретить повторное открытие.Контракт
IDisposable.Dispose
явно требует, чтобы вызов его для объекта, который никогда не будет использоваться снова, в худшем случае был бы безвредным, поэтому я бы рекомендовал вызывать либоIDisposable.Dispose
метод, либо метод, вызываемыйDispose()
для каждогоIDisposable
объекта, независимо от того, вызывает ли он также или нетClose()
.источник
Это старый вопрос, но теперь вы можете писать с использованием операторов без необходимости блокировать каждый из них. Они будут утилизированы в обратном порядке, когда содержащий блок будет закончен.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using
источник