Зачем мне нужно вызывать распоряжение на элементах управления ASP.NET? - PullRequest
10 голосов
/ 30 июня 2010

Я занимаюсь разработкой ASP.NET в VS и только что нашел интересное небольшое предложение кода (я думаю, что они получены от coderush, но я могу ошибаться).

Всякий раз, когда я создаю элементы управления, это говорит мне, что я должен использовать для них оператор "using". Я немного смущен тем, что здесь происходит, хотя. с использованием моего кода выглядит примерно так:

using (HtmlTableRow tableRow = new HtmlTableRow())
{
    tableRow.Attributes.Add("class", isOddRow ? "OddRow" : "EvenRow");
    listingTable.Rows.Add(tableRow);
    addCell(tableRow, row, "issueId");
    addCell(tableRow, row, "Title");
    addCell(tableRow, row, "Type");
    addCell(tableRow, row, "Summary");
}

Так что я ожидаю, что в конце оператора using он вызовет dispose для tableRow. Тем не менее, документы в библиотеке MSDN говорят:

Метод Dispose покидает Control в непригодном состоянии. После звонка этот метод, вы должны освободить все ссылки на контроль, так что память это занимало может быть утилизируется сборщиком мусора.

Так что я ожидаю, что теперь в моей структуре управления есть непригодный объект, чтобы он ломался или не рендерился или что-то в этом роде. Тем не менее, кажется, что все работает отлично.

Так что мне интересно, почему все элементы управления одноразовые? Не потому ли, что некоторые из них будут такими, и их создание одноразово означает, что один вызов для удаления на верхнем уровне может затем рекурсивно передаваться всем дочерним элементам управления?

Думаю, я бы понял, если бы не тот факт, что в документах прямо сказано, что удаление элемента управления делает его непригодным для использования ... Являются ли документы просто неправильными?

1 Ответ

14 голосов
/ 30 июня 2010

Ты не должен этого делать. Что вам нужно сделать, это убедиться, что listTable находится в коллекции Controls, чтобы он был удален при удалении страницы. Затем объект listTable отвечает за правильное удаление всех своих дочерних элементов.

Именно поэтому все Control объекты реализуют интерфейс IDisposable. Таким образом, каждый родительский элемент управления может вызывать Dispose для всех своих дочерних элементов без предварительного тестирования / приведения каждого из них. Каждый элемент управления индивидуально отвечает за определение того, есть ли на самом деле что-либо, что необходимо очистить при вызове его метода Dispose.

Документы не ошибаются. Любой правильно написанный объект, который реализует IDisposable и имеет данные о состоянии, которые фактически очищаются во время процесса удаления , должен вызывать исключение ObjectDisposedException, если после его удаления доступны какие-либо из его открытых / защищенных / внутренних свойств или методов. , (Допустим, недопустимое состояние после вызова Dispose.) Некоторые типы игнорируют это правило, если на самом деле им нечего очищать, и им не нужно беспокоиться о недопустимом состоянии.

Причина, по которой вы получаете предложение обернуть его в блок using, заключается в том, что анализатор не понимает, что listingTable будет располагать своей коллекцией Rows, которая будет располагать каждый из объектов строк, имеющих были добавлены к нему. Кроме того, если исключение создается между HtmlTableRow tableRow = new HtmlTableRow() и listingTable.Rows.Add(tableRow), объект HtmlTableRow будет «осиротевшим» и не будет находиться в иерархии IDisposable любого другого объекта. Анализ кода требует, чтобы вы использовали блок try / finally, чтобы немедленно избавиться от HtmlTableRow, если это произойдет.

...