Если экземпляр универсальной коллекции содержит элементы iDisposable, удаляются ли элементы?

Например:

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

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

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

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

Edit

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

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

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

Ответы

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

Изменить:

Следующий код реализует 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
}

Ответ 4

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