2010-02-01 8 views
6

È corretto inserire un "try/catch" all'interno di un'istruzione "using" per una richiesta web? Il mio codice è corretto? Ecco le mie esigenze sono:C# - è corretto inserire un "try/catch" all'interno di un'istruzione "using" per una richiesta web? Il mio codice è corretto?

  1. desidera utilizzare la "utilizzando" l'istruzione per assicurarsi che le risorse vengono rilasciati in ogni caso per HttpWebResponse

    • Ma ancora voglia di fare alcune cose personalizzato se v'è un exception re HttpWebResponse e "response = (HttpWebResponse) request.GetResponse();" in particolare.

mio codice sorgente:

 var result = new HttpHeaderInfo(); 
     HttpWebRequest request = null; 
     HttpWebResponse response = null; 
     using (response) 
     { 
      try 
      { 
       request = (HttpWebRequest)WebRequest.Create(uri); 
       request.Method = "HEAD"; 
       request.KeepAlive = false; 
       request.Timeout = Properties.Settings.Default.WebTimeoutDefault; 

       response = (HttpWebResponse)request.GetResponse(); 
       result.LastModified = response.LastModified; 
       result.ContentType = response.ContentType; 
       result.StatusCode = response.StatusCode; 
       result.ContentLength = response.ContentLength; 
      } 
      catch (Exception ex) 
      { 
       if (ex is InvalidOperationException || 
        ex is ProtocolViolationException || 
        ex is WebException) 
       { 
        result.HttpError = ex; 
        result.LastModified = System.DateTime.MinValue; 
        result.ContentType = null; 
       } 
       else { throw; } 
      } 

     } 

grazie

risposta

9

È OK, ma un po 'ridondante; in senso generale, è possibile rimuovere facilmente il blocco using, aggiungere un blocco finally dopo lo catch e chiamare esplicitamente lo Dispose in tale posizione, riducendo così il nidificazione nel codice.

In un senso più specifico, quello che mi bug un po 'è che in realtà non si assegna response fino ad arrivare all'interno il blocco using, e le dichiarazioni delle variabili esplicite sono inutili e confusa in questo contesto. Vorrei riscriverlo come:

HttpHeaderInfo result; 
try 
{ 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Method = "HEAD"; 
    request.KeepAlive = false; 
    request.Timeout = Properties.Settings.Default.WebTimeoutDefault; 

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
    { 
     result = new HttpHeaderInfo(); 
     result.LastModified = response.LastModified; 
     result.ContentType = response.ContentType; 
     result.StatusCode = response.StatusCode; 
     result.ContentLength = response.ContentLength; 
    } 
} 
catch (WebException ex) 
{ 
    // etc. 
} 

Questo è molto più chiaro rispetto alla forma originale. Si noti inoltre che sto rilevando WebException, non il generico System.Exception. Dovresti rilevare specifici tipi di eccezione invece di rilevare eccezioni generiche e quindi controllarne il tipo.

+0

grazie - hai notato che stavo effettivamente catturando solo 3 specifiche eccezioni nel mio codice - non ero sicuro di quanto estendere InvalidOperationException e ProtocolViolationException cuold sono stati trattati come errori di tipo di sistema (improbabile che si verifichino a meno che il tuo codice non abbia un problema) - Pensi che per HTTPWebRequest qui sia appropriato gestire solo WebException? – Greg

+0

@Greg: Probabilmente hai bisogno di gestire le altre eccezioni, semplicemente non volevo ingombrare l'esempio. Per farlo puoi aggiungere più blocchi 'catch' - la risposta di" Moron "mostra un esempio di come farlo. (Nota - Probabilmente prenderò "ProtocolViolationException" ma non "InvalidOperationException" - il primo deriva da quest'ultimo e non dovresti ottenere nessun altro tipo di "InvalidOperationException" da "GetResponse", non per quanto ne so comunque ...) – Aaronaught

1

Questo è del tutto OK. Gestisci l'eccezione e non vuoi che si spaventi più in là, va bene, e i blocchi try/catch/finally annidati non sono un problema. (Internamente un 'uso' come questo è solo un tentativo/finalmente.)

AGGIORNAMENTO: leggi un po 'più vicino, e penso che tu voglia effettivamente l'utilizzo all'interno del blocco' try '- la linea in cui effettivamente inserisci un oggetto nella variabile 'response' è dove vuoi che inizi il blocco 'using'. In realtà è compilato così com'è?

6

Altri hanno fatto notare come un potenziale problema, ma voglio alzare come un molto preciso problema: la vostra utilizzando dichiarazione che sta facendo bene a tutti in questo momento.

Quando si scrive un utilizzando dichiarazione come questa:

SomeType x = value1; 
using (x) 
{ 
    x = value2; 
} 

è value1 che sarà disposto in corrispondenza della fine del blocco, nonvalue2. Nel tuo codice, response è nullo fino all'interno del blocco; il WebResponse si finisce con lo non essere smaltiti.

dovreste vedere un avvertimento su questo, in queste righe:

avvertimento CS0728: assegnazione Possibilmente scorretto locale 'risposta', che è l'argomento di una dichiarazione di utilizzare o di blocco. La chiamata Dispose o lo sblocco avverrà sul valore originale del locale.

Questo avviso è importante - attenzione.

Lasciando a parte questo, è del tutto ragionevole per mettere un blocco try/catch in un'istruzione using ... ma in questo caso si deve probabilmente al di fuori l'istruzione using, lasciando che si inizializza la variabile response al momento opportuno in modo che la risposta venga sempre eliminata. Prenderò in considerazione l'utilizzo di più blocchi catch che chiamano un metodo comune anziché utilizzare "is" ripetutamente.

Problemi correlati