Подтвердить что ты не робот

Зачем мне нужно вызывать dispose на элементах управления ASP.NET?

Я занимаюсь разработкой 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");
}

Поэтому я ожидаю, что в конце используемого оператора он будет вызываться dispose на tableRow. Однако в документах в библиотеке MSDN говорится:

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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