Em C #, a using
instrução é usada para dispor de maneira determinística os recursos sem aguardar o coletor de lixo. Por exemplo, pode ser usado para:
Descarte comandos ou conexões SQL,
Feche os fluxos, liberando a fonte subjacente como um arquivo,
Elementos GDI + gratuitos,
etc.
Percebi que isso using
é usado cada vez mais nos casos em que não há nada a ser descartado, mas onde é mais conveniente para o chamador escrever um using
bloco em vez de dois comandos separados.
Exemplos:
O MiniProfiler , escrito pela equipe Stack Overflow, usa
using
para indicar blocos no perfil:using (profiler.Step("Name goes here")) { this.DoSomethingUseful(i - 1); }
Uma abordagem alternativa seria ter dois blocos:
var p = profiler.Start("Name goes here"); this.DoSomethingUseful(i - 1); profiler.Stop(p);
Outra abordagem seria usar ações:
profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
O ASP.NET MVC também selecionou os
using
formulários:<% using (Html.BeginForm()) { %> <label for="firstName">Name:</label> <%= Html.TextBox("name")%> <input type="submit" value="Save" /> <% } %>
Esse uso é apropriado? Como justificá-lo, uma vez que existem várias desvantagens:
Os iniciantes seriam perdidos, pois esse uso não corresponde ao explicado nos livros e nas especificações de idioma,
O código deve ser expressivo. Aqui, a expressividade sofre, pois o uso apropriado de
using
é mostrar que, por trás, existe um recurso, como um fluxo, uma conexão de rede ou um banco de dados que deve ser liberado sem aguardar o coletor de lixo.
fonte
using
: A última instrução (por exemploprofiler.Stop(p)
) não é garantida para ser executada diante de exceções e fluxo de controle.Respostas:
Sua última afirmação - de que "o uso apropriado do uso é mostrar que, por trás, existe um recurso, como um fluxo, uma conexão de rede ou um banco de dados que deve ser liberado sem esperar o coletor de lixo" está incorreto, e a razão pela qual é fornecido na documentação da interface IDisposable: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
Portanto, se sua classe usa recursos não gerenciados, não importa quando você pode ou não querer que o GC aconteça - não há nada a ver com o GC, pois os recursos não gerenciados não são gerados por GC ( https: // stackoverflow. com / questions / 3607213 / o que se entende por recursos gerenciados versus recursos não gerenciados na rede ).
Portanto, o objetivo de "usar" não é evitar a espera no GC, é forçar a liberação desses recursos não gerenciados agora , antes que a instância da classe saia do escopo e seja finalizada. Isso é importante por razões que devem ser óbvias - um recurso não gerenciado pode ter dependências de outros recursos não gerenciados e, se forem descartados (ou finalizados) na ordem errada, poderão ocorrer coisas ruins.
Portanto, se a classe que está sendo instanciada no bloco using usa recursos não gerenciados, a resposta é sim - é apropriado.
Observe que o IDisposable não é prescritivo, pois é apenas para liberar recursos não gerenciados - apenas que esse é seu objetivo principal . Ele pode ser o caso que o autor da classe tem alguma ação que eles querem impor acontecendo em um determinado momento, e implementar IDisposable pode ser uma maneira de conseguir que isso aconteça, mas se ou não isso é uma solução elegante é algo que pode só será respondido caso a caso.
Seja como for, o uso de "using" implica que a classe implemente IDisposable, para não violar a expressividade do código; deixa bem claro o que está acontecendo, de fato.
fonte
O uso de
using
implica a presença de umDispose()
método. Outros programadores assumirão que esse método existe no objeto. Consequentemente, se um objeto não é descartável, você não deve usáusing
-lo.A clareza do código é fundamental. Omitir
using
ou implementarIDisposable
no objeto.O MiniProfiler parece estar usando
using
como um mecanismo para "cercar" o código que está sendo criado. Há algum mérito nisso; presumivelmente, o MiniProfiler está chamandoDispose()
para parar um cronômetro ou o cronômetro é parado quando o objeto MiniProfiler fica fora do escopo.Em geral, você invocaria
using
quando algum tipo de finalização precisasse ocorrer automaticamente. A documentação parahtml.BeginForm
afirma que, quando o método é usado em umausing
instrução, ele renderiza a</form>
tag de fechamento no final dousing
bloco.Isso não significa necessariamente que ainda não é abuso.
fonte
IDisposable
/Dispose()
apesar de não ter nada a dispor no sentido que o OP está descrevendo?Dispose
é necessário parausing
fazer sentido em tudo (independentemente de se tratar de caso). Todos os exemplos do OP são implementadosDispose
, não é? E no IIUC, a questão é se é correto que essas classes usemDispose
, em vez de algum outro método (como oStop()
MiniProfiler).using
O erro e a exceção são seguros. Ele garanteDispose()
que será chamado independentemente dos erros cometidos pelo programador. Ele não interfere na captura ou no tratamento de exceções, mas oDispose()
método é executado recursivamente na pilha quando uma exceção é lançada.Objetos que implementam,
IDispose
mas não têm nada para descartar quando são concluídos. São, na melhor das hipóteses, protegendo seu design no futuro. Para que você não precise refatorar seu código-fonte, quando, no futuro, eles precisarem se desfazer de algo.fonte