2009-12-28 3 views
20

Jon тарелочкам made a comment (via Twitter) на мой SOApiDotNet кода (библиотека .NET для API до альфа переполнением стека):C#: "Использование" Заявления с HttpWebRequests/HttpWebResponses

@ maximz2005 Одна вещь, которую я заметил просто быстро просматривая исходный код: вы не используете (sic) WebResponses. «Использование» операторов FTW.

Он указывает, что мне нужно обернуть эти веб-сессии в выражениях «using». Однако у меня есть вопрос об этом: должен ли я обернуть все это, начиная с HttpWebRequest, или мне нужно создать WebRequest за пределами инструкции «using», а затем обернуть ответ в? У меня такое чувство, что разница в том, что в первом были уничтожены оба объекта - это правильно?

Заранее спасибо.

ответ

42

HttpWebRequest сам по себе не является одноразовым, в отличие от HttpWebResponse. Вы должны обернуть одноразовые ресурсы с помощью, чтобы разрешить раннюю и определенную очистку. Правильно выполненный шаблон IDisposable допускает множественные вызовы Dispose без каких-либо проблем, поэтому даже внешний оператор using обертывает ресурс, который во время своего собственного распоряжения предоставляет внутренний ресурс оператора, он все еще в порядке.

Пример кода

var request = (HttpWebRequest)WebRequest.Create("example.com"); 
using (var response = (HttpWebResponse)request.GetResponse()) 
{ 
    // Code here 
} 
+0

Так что я должен объявить ..Request снаружи или что? –

+2

Да, это означает, что вы выполнили бы запрос var = (HttpWebRequest) WebRequest.Create («http://example.com»); using (var response = (HttpWebResponse) request.GetResponse()) { // Код здесь } –

+1

@Dzmitry, @Benjamin. Я добавил пример кода Бенджамина к вашему ответу. –

6

Все, что связано с использованием() {} блока (то есть внутри первых скобок), расположено, когда вы покидаете область действия.

Я до сих пор не использовал вашу библиотеку (кажется приятным), но я бы сказал, что вы должны явно распоряжаться каждым созданным IDisposable (= несут ответственность) и не возвращаться к вызывающему.

Замечание, так как я видел много людей, борющихся с несколькими вещами распоряжаться: Вместо

using (var foo = SomeIDisposable) { 
    using (var bar = SomeOtherIDisposable) { 
    } 
} 

, который требует много вертикального пространства, которое вы можете написать

using (var foo = SomeIDisposable) 
using (var bar = SomeOtherIDisposable) { 
} 
+0

Ваш второй абзац (верный, я считаю) противоречит первому. Если все внутри блока использования расположено, вам не понадобится инструкция внутреннего использования. – Tomas

+0

Просмотреть мое обновленное сообщение: Все, что находится в использовании (...), расположено, когда вы покидаете следующий блок (эта часть: {...}) –

1

Для того, чтобы предотвратить утечку памяти вы должны вызвать Dispose на каждый объект, который реализует IDisposable. Вы можете убедиться, что метод Dispose вызывается с использованием ключевого слова using (не предназначенного для каламбура), поскольку это просто синтаксический сахар для блока try-finally.