Очистка коллекции коллекций - сначала очистить каждый элемент или просто очистить все сразу? - PullRequest
1 голос
/ 28 мая 2009

Предположим, у меня есть какая-то коллекция, которая сама содержит коллекции; например, словарь (из строки, список (из MyClass)). Если я хочу полностью очистить коллекцию, имеет ли смысл очищать каждую отдельную дочернюю коллекцию перед очисткой родительской коллекции, например:

For Each ListDef As KeyValuePair(Of String, List(Of MyClass)) In MasterDictionary
    Dim ThisList As List(Of MyClass) = ListDef.Value
    ThisList.Clear()
Next

MasterDictionary.Clear()

Или это действительно не более чем просто:

MasterDictionary.Clear()

Я спрашиваю, есть ли какая-либо причина - производительность, безопасность, ясность и т. Д. - использовать первый метод. Я обычно использую второй метод сам, поскольку я предполагаю, что он неявно достигает того, что делает первый метод в любом случае. Но мы все знаем, как опасно иногда предполагать; отсюда этот вопрос.

РЕДАКТИРОВАТЬ : Сегодня в моем собственном заявлении я нашел убедительные доказательства того, что первый метод может быть предпочтительным в определенных случаях. В моем приложении есть несколько глобальных коллекций (словари, содержащие списки, как в приведенном выше примере кода), которые заполняются, когда пользователь нажимает кнопку с надписью «Загрузить данные». Когда пользователь нажимает «Разгрузить данные», чтобы начать сначала, я ранее очищал эти коллекции, используя второй метод выше.

Проблема заключалась в том, что когда пользователь нажимал «Загрузить данные» во второй раз, приложение внезапно становилось очень медленным. В конце концов он снова закончит заполнять коллекции, но в темпе улитки. Я не мог понять, как решить эту проблему, пока я наконец не попробовал первый метод выше. Теперь перезагрузка и повторное заполнение коллекций работает так же быстро, как и загрузка их в первый раз.

Исходя из опубликованных ответов, похоже, что у меня должен быть "другой код где-то", ссылающийся на дочерние коллекции; однако, это не выглядит для меня как я. Единственные места, на которые я ссылаюсь на этих детей, это где я перебираю их родителей; если родители очищены, то у них не должно быть детей, о которых известно в коде, верно?

Надеюсь, кто-то может помочь мне понять, как эти ссылки все еще существуют, или что происходит, что я пропускаю.

Ответы [ 3 ]

4 голосов
/ 28 мая 2009

В обоих случаях вы не решаете никаких проблем утилизации отдельных элементов, содержащихся в дочерних коллекциях. В этом случае оба должны быть идентичны.

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

Если никакие другие ссылки не хранятся, то второй метод просто ожидает в GC очистки элементов. Отдельные ссылки будут обрабатываться GC в обоих случаях, поэтому различия в производительности будут незначительными. Лично я бы использовал второй метод, поскольку я считаю, что он более понятен (и его гораздо проще написать), и в большинстве случаев эффект будет менее удивительным, особенно если вы используете список в другом месте.

2 голосов
/ 28 мая 2009

Если нет других ссылок на «дочерние» коллекции, то Clear () в «родительской» коллекции приведет к очистке дочерних коллекций (и, соответственно, элементов в них) - в конце концов. Я бы сказал, что вы в безопасности, пока ни один из элементов дочерних коллекций не реализует IDisposable, поскольку это подразумевает, что у них заблокирован некоторый ресурс, и неправильная утилизация их может привести к проблемам в будущем.

1 голос
/ 28 мая 2009

Зависит от того, как в противном случае используется ваш код.

Если у вас есть другой код, где-то ссылающийся на какой-либо из List (Of MyClass), то, очевидно, эти списки будут тогда пустыми для другого кода, используя первый подход, тогда как в первом это не так.

Если есть какие-либо различия в производительности, которых я не знаю, и я полагаю, что лучший способ выяснить это - попытаться профилировать их. Можно подумать, что первый метод первоначально использует немного больше ресурсов процессора, но, возможно, меньше во время раунда GC - но на самом деле это тот случай, когда профилирование имеет смысл:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...