Classes, tais como Stream
, StreamReader
, StreamWriter
etc implementos IDisposable
interface. Isso significa que podemos chamar o Dispose()
método nos objetos dessas classes. Eles também definiram um public
método chamado Close()
. Agora, isso me confunde, sobre o que devo chamar quando terminar os objetos? E se eu ligar para os dois?
Meu código atual é este:
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();
}
}
Como você vê, escrevi using()
construções, que automaticamente chamam Dispose()
método em cada objeto. Mas eu também chamo Close()
métodos. Está certo?
Sugira-me as melhores práticas ao usar objetos de fluxo. :-)
O exemplo do MSDN não usa using()
construções e chama o Close()
método:
Isso é bom?
using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { }
. Quero dizer assim, onde você pode redefinir o tipo:using (MemoryStream ms = new MemoryStream()) using (FileStream fs = File.OpenRead("c:\\file.txt")) { }
Respostas:
Um rápido salto no Reflector.NET mostra que o
Close()
método ativadoStreamWriter
é:E
StreamReader
é:A
Dispose(bool disposing)
substituiçãoStreamReader
é:O
StreamWriter
método é semelhante.Portanto, lendo o código, fica claro que você pode ligar
Close()
eDispose()
transmitir sempre que quiser e em qualquer ordem. Não vai mudar o comportamento de forma alguma.Então, tudo se resume a saber se é ou não é mais legível para uso
Dispose()
,Close()
e / ouusing ( ... ) { ... }
.Minha preferência pessoal é que
using ( ... ) { ... }
sempre deve ser usado quando possível, pois ajuda você a "não correr com tesoura".Mas, embora isso ajude à correção, reduz a legibilidade. No C #, já temos uma infinidade de chaves de fechamento, então como sabemos qual delas realmente executa o fechamento no fluxo?
Então eu acho que é melhor fazer isso:
Não afeta o comportamento do código, mas ajuda na legibilidade.
fonte
Close()
chamada redundante . Se alguém menos experienteusing
examinar o código e não souber sobre ele: 1) procurará e aprenderá ou 2) adicionará um cegamenteClose()
manualmente. Se ele escolher 2), talvez algum outro desenvolvedor veja o redundanteClose()
e, em vez de "rir", instrua o desenvolvedor menos experiente. Não sou a favor de dificultar a vida de desenvolvedores inexperientes, mas sou a favor de transformá-los em desenvolvedores experientes.Não, você não deve chamar esses métodos manualmente. No final do
using
bloco, oDispose()
método é chamado automaticamente, o qual terá o cuidado de liberar recursos não gerenciados (pelo menos para as classes .NET BCL padrão, como fluxos, leitores / gravadores, ...). Então você também pode escrever seu código assim:O
Close()
método chamaDispose()
.fonte
using
o primeiro,responseStream
pois é embalado peloreader
que garantirá que seja fechado quando o leitor for descartado. +1 no entantoThe Close method calls Dispose.
... e no restante do seu post, você está insinuando queDispose()
chamariaClose()
, eu não deveria ligar manualmente para o último. Você está dizendo que eles se chamam?using
bloco. Estou implementando uma classe que escreve de tempos em tempos e, portanto, não pode.using
(ou, novamente, vá para o Dispose Pattern).A documentação diz que esses dois métodos são equivalentes:
Portanto, ambos são igualmente válidos:
Pessoalmente, eu continuaria com a primeira opção, pois ela contém menos "ruído".
fonte
Em muitas classes que suportam ambos
Close()
eDispose()
métodos, as duas chamadas seriam equivalentes. Em algumas classes, no entanto, é possível reabrir um objeto que foi fechado. Algumas dessas classes podem manter alguns recursos ativos após um fechamento, a fim de permitir a reabertura; outros podem não manter nenhum recurso ativoClose()
, mas podem definir um sinalizadorDispose()
para proibir explicitamente a reabertura.O contrato para
IDisposable.Dispose
explicitamente exige que chamá-lo em um objeto que nunca será usado novamente seja, na pior das hipóteses, inofensivo, portanto, recomendo chamarIDisposable.Dispose
um método ou um método chamadoDispose()
em cadaIDisposable
objeto, independentemente de alguém também chamarClose()
.fonte
Esta é uma pergunta antiga, mas agora você pode escrever usando instruções sem precisar bloquear cada uma. Eles serão descartados na ordem inversa quando o bloco de contenção for concluído.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using
fonte