2011-01-14 17 views
9

Vi esto. ¿Por qué el lanzamiento explícito a IDisposable? ¿Se trata simplemente de una abreviatura para garantizar que se llame a IDisposable al salir del bloque de uso?Tipo de lanzamiento a IDisposable - ¿Por qué?

using (proxy as IDisposable) 
{ 
    string s = proxy.Stuff()          
} 

Respuesta

25

Este "truco", si se puede llamar así, es probablemente debido a que proxy es de un tipo que el compilador no puede verificar realmente implementa IDisposable.

Lo bueno de la directiva using, es que si el parámetro a es null, entonces no hay ninguna llamada a Dispose se hará al salir del ámbito de la instrucción using.

Así que el código que has demostrado es realmente corto la mano para:

var disposable = proxy as IDisposable; 
try 
{ 
    string s = proxy.Stuff(); 
} 
finally 
{ 
    if (disposable != null) 
     disposable.Dispose(); 
} 

En otras palabras, se dice que "si este objeto implementa IDisposable, necesito disponer de él cuando he terminado con la siguiente pieza de código ".

+0

+1 para "si este objeto implementa IDisposable ..." – Justin

4

Es innecesario, ya que la declaración using está ligado explícitamente a la interfaz IDisposable, per the MSDN docs

Proporciona una sintaxis conveniente que asegura el correcto uso de los objetos IDisposable.

edición: El C# language spec (Sec. 8.13) proporciona tres expansiones posibles para el azúcar sintáctica de la declaración using:

A usando enunciado de la forma

using (ResourceType resource = expression) statement 

corresponde a una de las tres expansiones posibles. Cuando TipoRecurso es un tipo de valor no anulable, la expansión es

{ 
    ResourceType resource = expression; 
    try { 
     statement; 
    } 
    finally { 
     ((IDisposable)resource).Dispose(); 
    } 
} 

lo contrario, cuando TipoRecurso es un tipo de valor anulable o un tipo de referencia que no sea dinámica, la expansión es

{ 
    ResourceType resource = expression; 
    try { 
     statement; 
    } 
    finally { 
     if (resource != null) ((IDisposable)resource).Dispose(); 
    } 
} 

lo contrario, cuando TipoRecurso es dinámica, la expansión es

{ 
    ResourceType resource = expression; 
    IDisposable d = (IDisposable)resource; 
    try { 
     statement; 
    } 
    finally { 
     if (d != null) d.Dispose(); 
    } 
} 

Tenga en cuenta que en cada una de estas expansiones el reparto se realiza de todos modos, por lo que originalmente se dijo, el as IDisposable es innecesario.

+2

¿Qué pasa si "proxy" es un objeto que el programador "sabe" implementa IDisposable, pero el compilador no puede verificarlo? ¿Por qué el yeso no sería necesario entonces? –

+0

Sí, si hay alguna razón para que sea claro para el lector que 'proxy 'se extiende IDisposable – Will

+0

Siempre que su proxy no sea un proxy WCF, en cuyo caso no es seguro usar un bloque que use. Pero ese es otro tema. –

3

Esto podría ser necesario si se le proporciona una instancia proxy desde algún lugar y su tipo estático no implementa IDisposable, pero sabe que el tipo real puede funcionar y desea asegurarse de que se eliminará, p.

public class Proxy : ISomeInterface, IDisposable 
{ 
    ... 
} 

private ISomeInterface Create() { ... } 

ISomeInterface proxy = Create(); 

//won't compile without `as` 
using(proxy as IDisposable) 
{ 
    ... 
} 
+0

+1 También podría tener un ejemplo similar con genéricos. –

Cuestiones relacionadas