2010-09-02 12 views
6

To jest pytanie nawiązanie do thisKtóry jest szybszy - A Korzystanie blok lub try/catch/finally

powinienem trzymać z try/catch/finally budowy, lub iść z Korzystanie zbudować?

Przykładowy kod dla 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 

wiem co kod musiałby być dla Korzystanie skonstruować. Chcę tylko wiedzieć, czy użycie konstruktora Using będzie szybsze porównywanie cykli zegara.

+11

Opcja 'using' tag znacznie szybciej . Zapisał mi około 5 sekund pisania. – tidwall

Odpowiedz

9

Nie będzie różnicy w wydajności. using jest rozszerzany przez kompilator do bloku try/finally.

Zobaczysz, że następujące dwie metody kompilują się do identycznego IL.

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(); 
    } 
} 

IL wygenerowana w pierwszym przypadku jest:

 
.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 

W drugim przypadku z try/finally w C# otrzymujemy:

 
.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

Tęsknisz za tym. – tidwall

+0

@jojaba: Cóż, zdecydowałem się pójść bez haczyka w przykładzie dla uproszczenia. Jeśli spodziewasz się, że zwrócisz treść instrukcji użycia, możesz dodać próbę/catch. Należy jednak pamiętać, że w celu rzetelnego porównania należałoby dodać haczyk do obu metod, tj. Dodać połówki do wersji try/finally * i * dodać blok try/catch wewnątrz lub na zewnątrz instrukcji using. –

0

Muszę wierzyć, że używanie versus try/catch nie przyniesie żadnej różnicy w odniesieniu do wydajności w stosunku do kodu, który uruchamiasz wewnątrz tych konstrukcji.

2

using kompiluje się w try/catch/finally. Naprawdę nie widzę żadnej różnicy semantycznej ani wydajności, o ile prawidłowo wyrzucisz swój obiekt w przypadku instrukcji obsługi try/catch.

W każdym przypadku przejdź pod numer using, ponieważ automagicznie robi porządki (w rzeczywistości w klauzuli finally). Nawet jeśli istnieje różnica w wydajności, prawdopodobnie jest tak mało, że masz lepsze miejsca do optymalizacji.

0

Try/Catch/Finally jest szybszy.

1) 6,638 s: za pomocą znacznika
2) 6.265 s: próby/haczyk/wreszcie

uruchomiony to kilkanaście razy. Try/Catch/Finally zawsze wychodzi na wierzch.

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

Benchmark ma pewne problemy. Najważniejsze z nich to: Użyj "Stoper" do mierzenia, a nie "DateTime.Now". 'Stoper' używa licznika wydajności i zapewnia wyższą precyzję. Następnie uruchom kod bez dokonywania pomiarów, może to oznaczać pewien czas nagrzewania, który mierzy Twoja próbka. –

+1

W rzeczywistości, otrzymasz przeciwny wynik, jeśli najpierw umieścisz próbę/pętlę for-loop w kodzie, a następnie zmierzysz pętlę. –

Powiązane problemy