Если создается экземпляр общей коллекции, содержащей элементы iDisposable, удаляются ли эти элементы? - PullRequest
4 голосов
/ 30 января 2009

Например:

Queue<System.Drawing.SolidBrush> brushQ = new Queue<System.Drawing.SolidBrush>();
...
brushQ.Clear();

Если я явно не снимаю с очереди каждый элемент и не распоряжаюсь ими по отдельности, удаляются ли оставшиеся элементы при вызове Clear ()? Как насчет того, когда очередь собирается мусором?

Если предположить, что ответ "нет", то какова лучшая практика? Нужно ли вам всегда перебирать очередь и располагать каждый элемент?

Это может стать уродливым, особенно если вам нужно попытаться .. наконец, вокруг каждого распоряжения, в случае, если вы выбрасываете исключение.

Редактировать

Таким образом, кажется, что пользователь общей коллекции обременителен, чтобы знать, что, если элементы одноразовые (это означает, что они, вероятно, будут использовать неуправляемые ресурсы, которые не будут очищены сборщиком мусора), то:

  1. Когда вы удаляете предмет из коллекции, убедитесь, что вы удалили () его.
  2. НЕ ВЫЗЫВАЙТЕ Очистить (). Итерация по сбор и утилизация каждого пункт.

Может быть, в документации к родовым коллекциям следует упомянуть об этом.

Ответы [ 4 ]

5 голосов
/ 30 января 2009

Родовые коллекции на самом деле ничего не знают о типе объектов, которые они содержат, поэтому вызов Clear не заставит их вызывать Dispose () для элементов. GC в конечном итоге избавится от них, как только сама коллекция будет уничтожена, при условии, что ничто иное не имеет активной ссылки на один из этих элементов.

Если вы хотите, чтобы у объектов был вызван метод Dispose при вызове Clear для коллекции, вам потребуется извлечь собственную коллекцию, переопределить соответствующие методы и выполнить вызовы самостоятельно.

4 голосов
/ 30 января 2009

Когда вы ожидаете, что они будут уничтожены? Как коллекция узнает, есть ли в ней другие ссылки на объекты?

2 голосов
/ 30 января 2009

Дайте мне посмотреть, смогу ли я написать пример кода для этого.

Редактировать:

Следующий код реализует IDisposable Queue:

class DisposableQueue<T>:Queue<T>,IDisposable where T:IDisposable

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public virtual void Dispose(bool disposing) {
        if (disposing) {
            foreach (T type in this) {
                try
                {
                    type.Dispose();
                }
                finally {/* In case of ObjectDisposedException*/}
            }
        }
    }
    #endregion
}
0 голосов
/ 30 января 2009

Как уже говорили другие, этого не произойдет. Однако вы можете создать свой собственный метод расширения, чтобы избавиться от них, если хотите.

...