2012-03-26 11 views
1

In der Delphi-Welt, es durch einig, zumindest in Betracht gezogen wurde, bevorzugt, den Versuch NACH einer Ressourcenzuweisung zu stellen, wie zum Beispiel:Sollte der "Versuch" vor oder nach der Ressourcenzuweisung sein?

OracleCommand oc = new OracleCommand(query, con); 
try 
begin 
    oc.CommandType = CommandType.Text; 
    String s = oc.ExecuteScalar().ToString(); 
    try    
    return s;    
    except (on OracleException ex) 
    begin 
     ShowMessage(ex.Message); 
     result := string.Empty; 
    end; 
end 
finally 
begin 
    con.Close(); 
    con.Dispose(); 
end; 

Ist es das gleiche in C# oder „versuchen“ kommen sollte, vor der Ressourcenzuweisung:

try 
{ 
    OracleCommand oc = new OracleCommand(query, con); 
    oc.CommandType = CommandType.Text; 
    String s = oc.ExecuteScalar().ToString(); 
    try 
    { 
    return s; 
    } 
    catch (OracleException ex) 
    { 
    MessageBox.Show(ex.Message); 
    return string.Empty; 
    } 
} 
finally 
{ 
    con.Close(); 
    con.Dispose(); 
} 

?

+7

In C# verwenden wir 'using', wie es die Götter beabsichtigten. – cHao

+0

Ihr 'try' im C# -Beispiel macht keinen Sinn - das Zurückgeben eines Strings wird niemals eine' OracleException' auslösen.Vielleicht wollen Sie mehr Code in den "Versuch" stecken? –

+0

Es sollte nicht funktionieren Code. –

Antwort

5

Es gibt eine noch bessere Lösung: die using Aussage. Statt diesem Code können Sie die idiomatische

using (Connection con = /* some initialization logic */) 
{ 
    try 
    { 
     using (OracleCommand oc = new OracleCommand(query, con)) 
     { 
      oc.CommandType = CommandType.Text; 
      return oc.ExecuteScalar().ToString(); 
     } // oc is automatically disposed here 
    } 
    catch (OracleException ex) 
    { 
     MessageBox.Show(ex.Message); 
     return string.Empty; 
    } 
} // con is automatically disposed here 
+5

'OracleCommand' implementiert auch IDisposable. – user7116

+1

+1 - Wie auch immer, warum nicht OracleCommand? :) Ich mache immer –

0

Nein schreiben, genug in diesem Fall wäre nur eine try/catch zu haben, wie:

try 
    { 
     OracleCommand oc = new OracleCommand(query, con); 
     oc.CommandType = CommandType.Text; 
     return oc.ExecuteScalar().ToString(); 

    } 
    catch (OracleException ex) 
    { 
     MessageBox.Show(ex.Message); 
     return string.Empty; 
    } 
    } 
    finally 
    { 
     con.Close(); 
     con.Dispose(); 
    } 
+1

Art von übersprungen den Punkt dort, indem Sie nicht den Code zu Instanz con hinzufügen, die außerhalb des Versuches schließlich blockieren und dann eine endgültige Antwort sein würde. –

+0

Richtig, ich habe nur die * Idee * und nicht konkreten Code gezeigt. – Tigran

3

In Ihrem C#, loszuwerden Ihrer Innerer Versuch, es ist unnötig, wie ich nie ein return jemals so gescheitert gesehen habe. Sie können auch eine using-Anweisung für Ihre wegwerfbaren Typen verwenden, sie ruft Dispose auf, auch wenn eine Ausnahme auftritt.

try 
{ 
    using(OracleCommand oc = new OracleCommand(query, con)) 
    { 
     oc.CommandType = CommandType.Text; 
     String s = oc.ExecuteScalar().ToString(); 

     return s; 
    } 
} 
catch (OracleException ex) 
{ 
    // either do something meaningful here, or fail hard 
    MessageBox.Show(ex.Message); 
    throw; 
} 
+0

+1, beide Rücksendungen würden niemals fehlschlagen :) – user7116

3

Der richtige Ansatz wäre Ressource Akquisitionen innerhalb using -Blöcke zu platzieren:

try 
{ 
    // omit the OracleConnection using if you receive it from elsewhere 
    using (OracleConnection con = new OracleConnection(...)) 
    using (OracleCommand oc = new OracleCommand(query, con)) 
    { 
     oc.CommandType = CommandType.Text; 

     // nothing was going to be thrown with just 'return s' 
     return oc.ExecuteScalar().ToString(); 
    } 
} 
catch (OracleException ex) 
{ 
    MessageBox.Show(ex.Message); 
} 

return string.Empty; 
1

Jede Aussage, die möglicherweise sollte innerhalb des try Block sein ausfallen könnten, und das schließt auf jeden Fall eine Datenbankverbindung. Die Entscheidung darüber, wo dies zu platzieren ist, hat nichts mit Ressourcenallokation und -entsorgung zu tun.

Solange ein Objekt, das IDisposable implementiert, ordnungsgemäß entsorgt wird, haben Sie Ihre Arbeit erledigt. Dies ist ein über explizite Syntax mit einem try/finally-Block:

OracleConnection con; 
try { 
    con = new OracleConnection(); 
    // Do stuff here. 
} catch { 
    // Handle errors here. 
} finally { 
    if (con != null) 
     con.Dispose(); 
} 

oder eine using Aussage:

using (var con = new OracleConnection()) { 
    // Do stuff here. 
} 

Die using Aussage wird einen Versuch übersetzt/finally-Block. Wenn Sie jedoch einen catch Block möchten, müssen Sie entweder auf den ersten Stil zurückkommen oder einen inneren try/catch Block in Ihre Verwendung einfügen, was wahrscheinlich mehr Overhead, aber in den meisten Fällen unbemerkbar ist.

+0

Der Grund, warum es in Delphi über dem Versuch war (oder sein könnte) war, dass, wenn die Zuweisung fehlgeschlagen wäre, es sowieso mit dem internen Code der Komponente entsorgt würde. –

1

Sind das einige Leute wie in kompetenten?

Sie haben das in Delphi aus dem gleichen Grund getan, wie Sie es in C# tun würden.

Wenn das Erstellen einer Instanz von oracle command eine Ausnahme auslöst, wird schließlich ausgeführt und eine weitere geworfen, weil Ihre Instanz null ist, oder schlimmer noch, ein Müll.

Naff alles mit der Verwendung als solche zu tun, außer wenn Sie tun würden, müssten Sie nicht schließen und entsorgen. Wenn Sie DoSomethingElse() hatten; Dort werden verwaltete und nicht verwaltete Überlegungen in die Bin eingegeben.

Verwandte Themen