qué objetos objeto método metodos español ejemplos descriptores clases acceso c# scope using

objetos - ¿ en c# qué es método?



¿Es una mala práctica usar una instrucción using en una variable de nivel de clase? (4)

Tengo un código similar al siguiente.

class MyController { [ThreadStatic] private DbInterface db; public void ImportAllData() { using (db = new DbInterface()) { var records = PullData(); PushData(records); } } private DbRecord[] PullData() { return db.GetFromTableA(); } private void PushData(DbRecord[] records) { db.InsertIntoTableB(records); } }

La alternativa es mucho más engorrosa de mantener.

class MyController { public void ImportAllData() { using (var db = new DbInterface()) { var records = PullData(db); PushData(records, db); } } private DbRecord[] PullData(DbInterface db) { return db.GetFromTableA(); } private void PushData(DbRecord[] records, DbInterface db) { db.InsertIntoTableB(records); } }

Por lo que puedo ver, mi primera implementación:

  • es seguro para subprocesos (suponiendo que DbInterface es seguro para subprocesos),
  • impide que cualquier otro proceso toque la variable db , y
  • asegura que db siempre estará dispuesto, incluso durante una excepción.

¿Es una mala práctica usar la instrucción using en una variable con alcance de clase? ¿Me he perdido algo?


Aquí hay una alternativa:

sealed class MyImporter { private readonly DbInterface db; public MyImporter(DbInterface db) { this.db = db; } public void ImportAllData() { var records = PullData(); PushData(records); } private DbRecord[] PullData() { return db.GetFromTableA(); } private void PushData(DbRecord[] records) { db.InsertIntoTableB(records); } }

En este caso, retener la referencia es una parte clara de la responsabilidad de la clase. También ahora está aumentando la responsabilidad de la eliminación para el usuario. Esta construcción más explícita reduce la tentación de agregar características adicionales al ''Controlador'', que es la forma en que su primer enfoque puede ir mal en el largo plazo. Esencialmente hemos refactorizado la función de importación en una clase separada para que el acceso compartido al campo ya no sea un problema.


Para eso está el constructo. Sería cuidadoso acerca de poner un uso en la propiedad, ya que la convención dicta que el acceso a la propiedad es liviano y el usuario no necesariamente quiere activar un ciclo de creación y eliminación cuando creen que están accediendo a una variable.

Sin embargo, los comentarios a continuación sobre la estructura del código son importantes: si desea realizar la importación una vez, se convierte en un paso de configuración que los usuarios deben conocer. Si puede visualizar diferentes patrones de acceso, la configuración de inyección de dependencia le permite al usuario controlar la creación y eliminación de las conexiones.


Personalmente, prefiero tu segunda opción.

El problema con el primer diseño es que efectivamente se agrega un acoplamiento innecesario al diseño. PushData métodos PullData y PushData no se pueden usar solos; requieren que se llame ImportAllData a una llamada a ImportAllData u otro método que configure y limpie adecuadamente la variable db .

La segunda opción, aunque un poco más de código (aunque no mucho), hace que la intención sea muy clara para todos y cada uno de los métodos. Cada método sabe que debe funcionar en una instancia externa de DbInterface pasada. Hay pocas o ninguna posibilidad de que esto se use indebidamente en el futuro.


Su primera variante expone db fuera del alcance donde es administrado por el bloque de using . Eso abre la posibilidad de efectos secundarios no deseados. Por ejemplo, otro método podría usar o incluso disponer de db. Eso podría suceder si usted o un mantenedor posterior olvida el contrato implícito de db o incluso a través de un error tipográfico en el código.

No usaría la primera variante.