Nothing is perfect (and neither is using)

"But nothing is perfect in God's perfect plan
He only gave us the good things so we'd understand
What life without them would be"
("Nothing is perfect", Neil Young, 1985)

Retomando el tema de un post anterior relacionado con los patrones try-finally y la conveniencia de su utilización para garantizar la devolución de los recursos que una aplicación solicita en un contexto local, llamaremos hoy la atención sobre un caso en el que la utilización de la sentencia using es problemática y del que se ha empezado a hablar sobre todo a raíz de la aparición de WCF (Windows Communication Foundation) con .NET 3.0.

Como seguramente ya sabe, la sentencia using permite construir un objeto que implementa la interfaz IDisposable, garantizando que al finalizar la ejecución del bloque que acompaña a la sentencia, sea de la manera que sea (normalmente o debido a una excepción), se hará una llamada al método Dispose del objeto, asegurando de esta forma la liberación de los recursos asociados a él. Un ejemplo típico de uso de using (valga la redundancia :-) podría ser el siguiente:

  using (var sr = new System.IO.StreamReader("DATA.TXT"))
  {
    Console.WriteLine(sr.ReadToEnd());
  }

La semántica de using determina que la sentencia anterior es equivalente a:

  var sr = new System.IO.StreamReader("DATA.TXT");
  try
  {
    Console.WriteLine(sr.ReadToEnd());
  }
  finally
  {
    sr.Dispose();
  }

Hasta aquí, todo genial; pero solo si asumimos que, según proponen las guías generales de diseño de clases de .NET, Dispose no lanza excepciones. Si Dispose puede lanzar excepciones, el using tiene dos problemas serios: a) en caso de que el código del bloque lance una excepción E1, y esa excepción desencadene otra excepción E2 en la llamada a Dispose, la segunda excepción ocultará a la primera ante el contexto de ejecución; b) independientemente de que el código del bloque lanzara o no excepción alguna, pero la llamada implícita a Dispose sí lo hiciera, el lugar de la excepción podría no ser evidente para un programador que examine el código fuente. En cualquiera de los casos, está claro que si Dispose lanzara una excepción las instrucciones que sigan a la instrucción using en el código no se ejecutarán.

La guía de diseño antes referenciada dice literalmente "Evite lanzar una excepción desde dentro de Dispose, excepto en situaciones críticas en las que el proceso contenedor esté corrupto" (no sé si la guía habrá cambiado algo en la reciente segunda edición de "Framework Design Guidelines", que aún no tengo). El caso es que esto no ocurre en el caso de los proxies de servicios WCF, cuyo método Dispose (al igual que su medio hermano Close) puede lanzar CommunicationObjectFaultedException. Esta página de MSDN alerta del hecho, y presenta la manera recomendada de trabajar con los proxies WCF. Dino Esposito también describe detalladamente la situación en el ejemplar nº 56 de dotNetManía.

¡Queda advertido!


Pop/rock tip: Neil Young es un cantante y guitarrista con más de 40 años de carrera, ya sea como miembro de bandas como Buffalo Springfield o Crosby, Stills, Nash & Young, en solitario o acompañado de su propia banda, Crazy Horse. Por el volumen e influencia de su obra,  All Music Gude lo sitúa en segundo lugar entre los intérpretes de su generación, solo por detrás de Bob Dylan. Su tema más conocido es "Heart of Gold", que la revista Rolling Stone colocó en el lugar 297 de las 500 mejores canciones de todos los tiempos.

 

Published 19/2/2009 22:19 por Octavio Hernández
Archivado en: ,
Comparte este post:

Comentarios

Thursday, May 13, 2010 11:03 PM por Espacio Digital

# Usando using, valga la redundancia (C#)

La palabra reservada using tiene diversos usos en el lenguaje C#, y seguro que muchos la utilizamos exclusivamente para importar espacios de nombres (namespaces), ignorando el resto de posibilidades q ...