¿Abusar de IDisposible beneficiarse de las declaraciones de “uso” se considera perjudicial?

El propósito de la interfaz IDisposable es liberar recursos no administrados de manera ordenada. Va de la mano con la palabra clave using que define un scope después del final del cual se dispone el recurso en cuestión.

Debido a que este meachnism es tan nítido, he tenido la tentación repetida de que las clases implementen IDisposable para poder abusar de este mecanismo de una forma que no está prevista. Por ejemplo, uno podría implementar clases para manejar contextos nesteds como este:

 class Context : IDisposable { // Put a new context onto the stack public static void PushContext() { ... } // Remove the topmost context from the stack private static void PopContext() { ... } // Retrieve the topmost context public static Context CurrentContext { get { ... } } // Disposing of a context pops it from the stack public void Dispose() { PopContext(); } } 

El uso en el código de llamada podría verse así:

 using (Context.PushContext()) { DoContextualStuff(Context.CurrentContext); } // <-- the context is popped upon leaving the block 

(Tenga en cuenta que esto es solo un ejemplo y no el tema de esta pregunta).

El hecho de que se Dispose() al abandonar el scope de la statement de using también se puede aprovechar para implementar todo tipo de cosas que dependen del scope, por ejemplo, los temporizadores. Esto también podría manejarse utilizando un try ... finally construir try ... finally , pero en ese caso el progtwigdor tendría que llamar manualmente algún método (por ejemplo, Context.Pop ), que el constructo que using podría hacer por thon.

Este uso de IDisposable no coincide con su propósito previsto como se indica en la documentación , pero la tentación persiste.

¿Hay razones concretas para ilustrar que esto es una mala idea y disipar mis fantasías para siempre, por ejemplo, las complicaciones con la recolección de basura, el manejo de excepciones, etc. ¿O debo seguir adelante y complacerme abusando de este concepto de lenguaje de esta manera?

Así que en las vistas de asp.net MVC, vemos la siguiente construcción:

 using(Html.BeginForm()) { //some form elements } 

¿Un abuso? Microsoft dice que no (indirectamente).

Si tienes una construcción que requiere que algo suceda una vez que hayas terminado, IDisposable menudo puede funcionar bastante bien. He hecho esto más de una vez.

“¿Es un abuso de la interfaz IDisposable usarla de esta manera”? Probablemente.

¿Usar el using como una construcción puramente de “scope” hace que la intención sea más obvia y la mejor legibilidad del código? Ciertamente.

Lo último le gana a lo primero, por eso digo que lo usen.

Ciertamente, no serías el primero en ‘abusar’ de IDisposible de esa manera. Probablemente mi uso favorito sea en los temporizadores, como lo demuestra el cliente StatsD.NET :

 using StatsdClient; ... using (statsd.LogTiming( "site.db.fetchReport" )) { // do some work } // At this point your latency has been sent to the server 

De hecho, estoy bastante seguro de que los mismos Microsoft lo usan en algunas bibliotecas. Mi regla de oro sería: si mejora la legibilidad, adelante.