Pergunta

Algo como:

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

Eu acredito que não é um lugar adequado para uma instrução de retorno, não é?

Foi útil?

Solução

Como vários outros apontaram, em geral, isso não é um problema.

O único caso que fará com que você emite é se você voltar no meio de uma instrução using e, adicionalmente, devolver o no uso variável. Mas, novamente, isso também faria com que você emite, mesmo se você não voltar e simplesmente manteve uma referência a uma variável.

using ( var x = new Something() ) { 
  // not a good idea
  return x;
}

Assim como mau

Something y;
using ( var x = new Something() ) {
  y = x;
}

Outras dicas

É perfeitamente bem.

Você está aparentemente pensando que

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

é cegamente traduzido em:

IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();

O que, na verdade, seria um problema, e gostaria de fazer a declaração using bastante inútil --- que é por isso que é não o que faz.

O compilador garante que o objeto é descartado antes das folhas de controle do bloco - independentemente de como ele deixa o bloco

.

É absolutamente bem - não há problema em tudo. Por que você acredita que é errado?

A instrução using é apenas açúcar sintático para um try / finally bloco, e como Grzenio diz que é bom para o retorno de um bloco try também.

A expressão de retorno serão avaliados, em seguida, o bloco finally será executado, em seguida, o método irá retornar.

Isto irá funcionar perfeitamente bem, assim como o retorno no meio da try{}finally{}

Isso é totalmente aceitável. A usando declaração garante o objeto IDisposable serão eliminados não importa o que.

A partir MSDN :

Os utilizando garante declaração que Dispose é chamado, mesmo se uma exceção ocorre enquanto você está chamando métodos no objeto. Você pode conseguir o mesmo resultado, colocando o objeto dentro de um bloco try e, em seguida, chamar Dispose em um bloco, finalmente; Na verdade, esta é a forma como a declaração usando é traduzido pelo compilador.

O código abaixo mostra como using está trabalhando:

private class TestClass : IDisposable
{
   private readonly string id;

   public TestClass(string id)
   {
      Console.WriteLine("'{0}' is created.", id);
      this.id = id;
   }

   public void Dispose()
   {
      Console.WriteLine("'{0}' is disposed.", id);
   }

   public override string ToString()
   {
      return id;
   }
}

private static TestClass TestUsingClose()
{
   using (var t1 = new TestClass("t1"))
   {
      using (var t2 = new TestClass("t2"))
      {
         using (var t3 = new TestClass("t3"))
         {
            return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
         }
      }
   }
}

[TestMethod]
public void Test()
{
   Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}

Output:

't1' é criado.
'T2' é criado.
'T3' é criado.
'Criado a partir de T1, T2, T3' é criado.
'T3' é descartado.
'T2' é descartado.
'T1' é descartado.

O disposto são chamados após a instrução de retorno, mas antes da saída da função.

Talvez não seja 100% verdade que isso é aceitável ...

Se acontecer de você ser usings nidificação e retornando a partir de dentro um aninhado, ele pode não ser seguro.

Leve isso como um exemplo:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
            return memoryStream.ToArray();
        }
    }
}

Eu estava passando em uma DataTable a ser emitida como CSV. Com o retorno no meio, ele estava escrevendo todas as linhas para o fluxo, mas o CSV emitido estava sempre faltando uma linha (ou múltiplos, dependendo do tamanho do buffer). Este disse-me que algo não estava sendo fechada corretamente.

A maneira correta é certificar-se todos os usings anteriores são eliminados corretamente:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
        }
    }

    return memoryStream.ToArray();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top