C#: "Использование" операторов с HttpWebRequests/HttpWebResponses
Джон Скит (через Twitter) прокомментировал мой код SOApiDotNet (библиотека.NET для API-интерфейса переполнения стека до альфа-версии):
@ maximz2005 Одна вещь, которую я заметил только после быстрого просмотра источника: вы не избавлялись (так) от WebResponses. "используя" заявления FTW.
Он указывает, что мне нужно обернуть эти веб-сеансы в операторы "using". Тем не менее, у меня есть вопрос по этому поводу: должен ли я обернуть все это, начиная с HttpWebRequest, или я должен создать WebRequest вне оператора "using", а затем обернуть Response внутри? У меня такое ощущение, что разница в том, что в первом случае оба объекта будут утилизированы - это правильно?
Заранее спасибо.
3 ответа
HttpWebRequest
сам по себе не одноразовый в отличие HttpWebResponse
, Вы должны обернуть одноразовые ресурсы с помощью, чтобы позволить раннюю и решительную очистку. Правильно реализовано IDisposable
шаблон позволяет несколько звонков Dispose
без каких-либо проблем, так что даже внешний оператор using оборачивает ресурс, который во время его собственной утилизации располагает внутренним ресурсом using, он все еще в порядке.
Пример кода
var request = (HttpWebRequest)WebRequest.Create("example.com");
using (var response = (HttpWebResponse)request.GetResponse())
{
// Code here
}
Все, что заключено в блок using () {} (то есть внутри первых скобок), удаляется при выходе из области видимости.
До сих пор я не использовал вашу библиотеку (хотя это и выглядит неплохо), но я бы сказал, что вы должны явно распоряжаться каждым IDisposable, который вы создаете (= несете ответственность), и не возвращаться к вызывающей стороне.
Обозначение, так как я видел, как многие люди борются с множеством вещей, чтобы избавиться: вместо
using (var foo = SomeIDisposable) {
using (var bar = SomeOtherIDisposable) {
}
}
который требует много вертикального пространства, вы можете написать
using (var foo = SomeIDisposable)
using (var bar = SomeOtherIDisposable) {
}
Чтобы предотвратить утечки памяти, вы должны вызывать Dispose для каждого объекта, который реализует IDisposable. Вы можете убедиться, что метод Dispose вызывается с помощью ключевого слова using (без каламбура), так как это всего лишь синтаксический сахар для блока try-finally.