2010-02-01 1 views
6

웹 요청에 "사용"문 안에 "try/catch"를 포함해도 괜찮습니까? 내 코드가 맞습니까?C# - 웹 요청에 "using"문 내에 "try/catch"를 포함해도 괜찮습니까? 내 코드가 맞습니까?

  1. 가 HttpWebResponse 클래스

    • 에 대해 어떤 경우에도 공개되어 있는지 자원을 만들기 위해 "사용"문을 사용하고 싶지만 아직이 경우 일부 사용자 지정 물건을하고 싶지 : 그건 내 요구 사항이 있습니다 예외 HttpWebResponse 및 "응답 = (HttpWebResponse) request.GetResponse();" 특히.

내 소스 코드 :

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

     } 

감사

답변

9

괜찮지 만 약간 중복됩니다. 일반적으로 using 블록을 쉽게 제거 할 수 있으며 catch 다음에 finally 블록을 추가하고 명시 적으로 Dispose을 호출하면 코드의 중첩이 줄어 듭니다. 보다 구체적인 의미에서

, 무슨 버그 나 좀하면 내부 using 블록을 얻고, 명시 적 변수 선언이 상황에서 불필요한 혼란 때까지 당신이 실제로 response을 지정하지 않는다는 것입니다. 나는 다음과 같이 다시 써야합니다 :

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. 
} 

이것은 원래 형식보다 훨씬 명확합니다. 또한 WebException을 잡기 때문에 일반 System.Exception이 아닙니다. 일반 예외를 포착하고 유형을 확인하는 대신 특정 예외 유형을 포착해야합니다.

+0

감사합니다 - 효과적으로 효과적으로 내 코드에서 3 예외를 캡처했다 - 당신이 InvalidOperationException 및 ProtocolViolationException cuold 확장 할 수 있는지 확실하지 않았다 시스템 유형 오류 (하나의 코드가 문제가 발생하지 않는 것) - HTTPWebRequest에 대해 여기서는 WebException 만 처리하는 것이 적절하다고 생각합니까? – Greg

+0

@ 그렉 : 당신은 아마 다른 예외를 처리 할 필요가 있습니다. 나는 예제를 혼란스럽게하고 싶지 않습니다. 그렇게하기 위해 여러 개의 'catch'블록을 추가 할 수 있습니다. - "Moron 's"응답은이를 수행하는 예를 보여줍니다. (주의 - 아마도'ProtocolViolationException'을 잡을 수는 있지만'InvalidOperationException'은 잡을 수 없을 것입니다 - 전자는 후자에서 파생되며 GetResponse에서 다른 유형의'InvalidOperationException'을 얻지 않아야합니다.) – Aaronaught

1

이 완전히 OK이다. 예외를 처리하고 더 이상 버블 링하는 것을 원하지는 않습니다. 그냥 잘되고 중첩 된 try/catch/finally 블록은 아무런 문제가되지 않습니다. (내부적으로 'using'은 단지 try/finally입니다.)

업데이트 : 조금 더 가까이서 읽으십시오. 실제로 'try'블록 내부에서 사용하고 싶다고 생각합니다. 실제로는 객체를 넣는 선 '응답'변수에서 '사용'블록을 시작하기를 원합니다. 실제로 컴파일 한 상태입니까?

6

다른 사람들은 잠재적 문제로이 문제를 지적했지만, 나는 매우 명확한 문제로 제기 할 : 당신의 using 문을 순간에 모든 당신에게 좋은 일을하지 않습니다.

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

는 블록의 끝 부분에 배치됩니다 value1입니다 하지value2 :

는이 같은 사용하여 명령문을 작성합니다. 코드에서 response은 블록 내부까지는 null입니다. WebResponse으로 끝나면 이 아닌이 처리됩니다.

당신은이 라인을 따라, 이것에 대해 경고가 표시되어야합니다

경고 CS0728 : 이 사용하거나 잠금 문에 인수입니다 지역 '응답'에 아마 잘못된 할당. Dispose 통화 또는 잠금 해제는 로컬의 원래 값에서 발생합니다.

경고가 중요합니다.주의하십시오. 그 옆을 떠나

, 그것을 사용하여 문에서 try/catch 블록을 넣어 완전히 합리적인 ...하지만이 경우에는 아마 당신이 적절한 시간에 response 변수를 초기화시키는, using 문 외부해야한다 응답은 항상 처리됩니다. 나는 또한 반복적으로 "is"를 사용하는 것이 아니라 일반적인 방법을 호출하는 여러 catch 블록을 사용하는 것을 고려할 것이다.

관련 문제