2010-09-02 22 views
6

Ésta es una pregunta de seguimiento a thisque es más rápido - Un bloque Usar o try/catch/finally

¿Debo seguir con el try/catch/Finalmente construir, o ir con el uso de la construcción?

Código de ejemplo para Try/catch/finally:

Dim oRequest As WebRequest 
Dim oResponse As HttpWebResponse = Nothing 
Dim dataStream As Stream = Nothing 
Dim reader As StreamReader = Nothing 
Dim responseFromServer As String 

Try 
     sNewCustomerURL = NewCustomerQueryStringPrepare() 

    'make the call to the webservice to add a new customer 
    oRequest = WebRequest.Create(sNewCustomerURL) 

    oRequest = CType(oRequesC, HttpWebRequest) 
    oRequest.Method = "GET" 
    oResponse = CType(oRequest.GetResponse(), HttpWebResponse) 

    dataStream = oResponse.GetResponseStream() 
    reader = New StreamReader(dataStream) 
    responseFromServer = reader.ReadToEnd() 

     Dim xml As New XmlDocument() 
    xml.LoadXml(responseFromServer) 
    Dim node As XmlNodeList = xml.GetElementsByTagName("SUCCESS") 
    Dim value = CBool(node(0).InnerText) 

    'do stuff    


Catch ex As Exception 

     'process exception 

Finally 

    'do cleanup 
    oRequest = Nothing 
    If Not oResponse Is Nothing Then 
     oResponse.Close() 
    End If 
    oResponse = Nothing 
    If Not reader Is Nothing Then 
     reader.Close() 
    End If 
    reader = Nothing 
    If Not dataStream Is Nothing Then 
     dataStream.Flush() 
     dataStream.Close() 
    End If 
    dataStream = Nothing 
End Try 

sé lo que tendría que ser para el uso de construir el código. Solo quiero saber si usar el constructo Using sería más rápido comparando ciclos de reloj.

+11

La etiqueta 'using' mucho más rápido . Me salvó unos 5 segundos de tipeo. – tidwall

Respuesta

9

No habrá una diferencia de rendimiento. using es expandido por el compilador a un bloque try/finally.

Verá que los dos métodos siguientes se compilan en IL idénticos.

void SampleWithUsing() 
{ 
    using (MemoryStream s = new MemoryStream()) 
    { 
     s.WriteByte(1); 
    } 
} 

void SampleWithTryFinally() 
{ 
    MemoryStream s = new MemoryStream(); 
    try 
    { 
     s.WriteByte(1); 
    } 
    finally 
    { 
     if (s != null) s.Dispose(); 
    } 
} 

La IL genera en el primer caso es:

 
.method private hidebysig instance void SampleWithUsing() cil managed 
{ 
    // Code size  26 (0x1a) 
    .maxstack 2 
    .locals init ([0] class [mscorlib]System.IO.MemoryStream s) 
    IL_0000: newobj  instance void [mscorlib]System.IO.MemoryStream::.ctor() 
    IL_0005: stloc.0 
    .try 
    { 
    IL_0006: ldloc.0 
    IL_0007: ldc.i4.1 
    IL_0008: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8) 
    IL_000d: leave.s IL_0019 
    } // end .try 
    finally 
    { 
    IL_000f: ldloc.0 
    IL_0010: brfalse.s IL_0018 
    IL_0012: ldloc.0 
    IL_0013: callvirt instance void [mscorlib]System.IDisposable::Dispose() 
    IL_0018: endfinally 
    } // end handler 
    IL_0019: ret 
} // end of method Program::SampleWithUsing 

En el segundo caso con un try/finally en C# obtenemos:

 
.method private hidebysig instance void SampleWithTryFinally() cil managed 
{ 
    // Code size  26 (0x1a) 
    .maxstack 2 
    .locals init ([0] class [mscorlib]System.IO.MemoryStream s) 
    IL_0000: newobj  instance void [mscorlib]System.IO.MemoryStream::.ctor() 
    IL_0005: stloc.0 
    .try 
    { 
    IL_0006: ldloc.0 
    IL_0007: ldc.i4.1 
    IL_0008: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8) 
    IL_000d: leave.s IL_0019 
    } // end .try 
    finally 
    { 
    IL_000f: ldloc.0 
    IL_0010: brfalse.s IL_0018 
    IL_0012: ldloc.0 
    IL_0013: callvirt instance void [mscorlib]System.IO.Stream::Dispose() 
    IL_0018: endfinally 
    } // end handler 
    IL_0019: ret 
} // end of method Program::SampleWithTryFinally 
+0

Te estás perdiendo la trampa allí. – tidwall

+0

@jojaba: Bueno, decidí ir sin atrapar en el ejemplo por simplicidad. Si esperas que el cuerpo de la sentencia using arroje, podrías agregar un try/catch. Pero tenga en cuenta que para una comparación justa, debería agregar la captura a ambos métodos, es decir, agregar un catch a la versión try/finally * y * agregar un bloque try/catch dentro o fuera de la instrucción using también. –

0

Tengo que creer que usar versus try/catch no va a hacer ninguna diferencia en cuanto al rendimiento en relación con el código que está ejecutando dentro de esas construcciones.

2

using compila en try/catch/finally. Realmente no veo ninguna diferencia semántica o de rendimiento, siempre que deseche correctamente su objeto en el caso de un manual try/catch.

En cualquier caso, vaya con using, ya que limpia automágicamente (en realidad en la cláusula finally) para usted. Incluso si hay una diferencia de rendimiento, es probable que sea tan mínimo que tenga mejores lugares para optimizar.

0

Try/Catch/Finally es más rápido.

1) 6,638 seg: el uso de la etiqueta
2) 6,265 seg: try/catch/finally

me encontré con esto una docena de veces. Try/Catch/Finalmente siempre salió en la parte superior.

DateTime start = DateTime.Now; 
for (int i = 0; i < 50000000; i++) 
{ 
    using (MemoryStream s = new MemoryStream()) 
    { 
     s.WriteByte(1); 
    } 
} 
Console.WriteLine(DateTime.Now.Subtract(start) + " seconds"); 
start = DateTime.Now; 
for (int i = 0; i < 50000000; i++) 
{ 
    MemoryStream s = null; 
    try 
    { 
     s = new MemoryStream(); 
     s.WriteByte(1); 
    } 
    catch { } 
    finally 
    { 
     if (s != null) s.Dispose(); 
    } 
} 
Console.WriteLine(DateTime.Now.Subtract(start) + " seconds"); 
+2

El índice de referencia tiene algunos problemas. Los más importantes son: Use un 'Cronómetro' para medir y no' DateTime.Now'. 'Cronómetro' utiliza un contador de rendimiento y le da una mayor precisión. Luego, ejecute el código sin medir primero, puede haber un tiempo de calentamiento que su muestra midió. –

+1

De hecho, obtendrá el resultado opuesto si coloca primero el try/finally for-loop en su código y luego mide el ciclo de utilización. –

Cuestiones relacionadas