Pergunta

Se eu tenho a seguinte situação:

StreamWriter MySW = null;
try
{
   Stream MyStream = new FileStream("asdf.txt");
   MySW = new StreamWriter(MyStream);
   MySW.Write("blah");
}
finally
{
   if (MySW != null)
   {
      MySW.Flush();
      MySW.Close();
      MySW.Dispose();
   }
}

Posso apenas chamar MySW.Dispose() e pular o próximo mesmo que é fornecido? Há algum implimentations riacho que não funcionam como esperado (como CryptoStream)?

Se não, então é o seguinte código apenas ruim:

using (StreamWriter MySW = new StreamWriter(MyStream))
{
   MySW.Write("Blah");
}
Foi útil?

Solução

Posso apenas chamar MySW.Dispose () e pular o Fechar embora seja fornecidas?

Sim, isso é o que é para.

Existem quaisquer implementações Corrente que não funcionam como esperado (como CryptoStream)?

É seguro assumir que se um objeto implementa IDisposable, vai dispor de si corretamente.

Se isso não acontecer, então isso seria um erro.

Se não, então é o seguinte apenas má código:

Não, esse código é a maneira recomendada de lidar com objetos que implementam IDisposable.

Mais informação excelente é na resposta aceita a e Descarte - que chamar?

Outras dicas

Eu usei refletor e descobriu que parece System.IO.Stream.Dispose assim:

public void Dispose()
{
    this.Close();
}

Como Daniel Bruckner mencionado, Descarte e Fechar são efetivamente a mesma coisa.

No entanto fluxo não chamar flush () quando ele é descartado / fechado. FileStream (e eu assumir qualquer outra corrente com um mecanismo de cache) embutida faz chamada () quando dispostas.

Se você está estendendo Stream, ou MemoryStream etc você precisará implementar uma chamada para flush () quando descartado / fechado, se for necessário.

Ambos StreamWriter.Dispose () e Stream.Dispose () liberar todos os recursos mantidos pelos objetos. Ambos fechar o fluxo subjacente.

O código fonte do Stream.Dispose () (note que este é detalhes de implementação por isso não contar com ele):

public void Dispose()
{
    this.Close();
}

StreamWriter.Dispose () (mesmo que com Stream.Dispose ()):

protected override void Dispose(bool disposing)
{
    try
    {
        // Not relevant things
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            try
            {
                if (disposing)
                {
                    this.stream.Close();
                }
            }
            finally
            {
                // Not relevant things
            }
        }
    }
}

Ainda assim, eu geralmente implicitamente córregos próximos / streamwriters antes de descartá-los - eu acho que parece mais limpo

.

Todos os fluxos padrão (FileStream, CryptoStream) tentará rubor quando fechado / descartado. Eu acho que você pode contar com isso para qualquer implementações de fluxo da Microsoft.

Como resultado, fim / Descarte pode lançar uma exceção se o flush falhar.

Na verdade IIRC havia um bug na implementação .NET 1.0 de FileStream na medida em que não seria suficiente para liberar o identificador de arquivo se o flush lança uma exceção. Este foi fixo em .NET 1,1 por adição de uma tentativa / finalmente bloquear o método Descarte (booleano).

Para os objetos que precisam ser fechados manualmente, todos os esforços devem ser feitos para criar o objeto em um bloco usando.

//Cannot access 'stream'
using (FileStream stream = File.Open ("c:\\test.bin"))
{
   //Do work on 'stream'
} // 'stream' is closed and disposed of even if there is an exception escaping this block
// Cannot access 'stream' 

Desta forma pode-se nunca mais incorretamente o acesso 'stream' fora do contexto da cláusula de usar eo arquivo está sempre fechada.

Eu olhei na fonte .net para a classe Stream, que tinha o seguinte o que sugere que sim você pode ...

    // Stream used to require that all cleanup logic went into Close(),
    // which was thought up before we invented IDisposable.  However, we 
    // need to follow the IDisposable pattern so that users can write
    // sensible subclasses without needing to inspect all their base
    // classes, and without worrying about version brittleness, from a
    // base class switching to the Dispose pattern.  We're moving 
    // Stream to the Dispose(bool) pattern - that's where all subclasses
    // should put their cleanup starting in V2. 
    public virtual void Close() 
    {
        Dispose(true); 
        GC.SuppressFinalize(this);
    }

    public void Dispose() 
    {
        Close(); 
    } 

Stream.Close é implementado por uma chamada para Stream.Dispose ou vice-versa - para que os métodos são equivalentes. existe Stream.Close só porque fecham um sons de fluxo mais natural do que a eliminação de um córrego.

Além disso, você deve tentar evitar chamadas explícita a esta métodos e usar a instrução using vez a fim de obter exceção correta manipulação de graça.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top