Пара моментов:
Вызов Dispose
не увеличивает производительность.IDisposable
разработан для сценариев, в которых вы используете ограниченные и / или неуправляемые ресурсы, которые не могут быть учтены средой выполнения.
Не существует четкого и очевидного механизма того, как компилятор может обрабатывать IDisposable
объектыв коде.Что делает его кандидатом на автоматическое удаление, а что нет?Если экземпляр (или мог) быть представлен вне метода?Нечего и говорить, что только потому, что я передаю объект другой функции или классу, который я хочу, чтобы он был пригоден для использования вне рамок метода
Рассмотрим, например, фабричный шаблон, который принимает Stream
идесериализует экземпляр класса.
public class Foo
{
public static Foo FromStream(System.IO.Stream stream) { ... }
}
И я называю это:
Stream stream = new FileStream(path);
Foo foo = Foo.FromStream(stream);
Теперь я могу или не хочу, чтобы Stream
был удален при выходе из метода,Если фабрика Foo
считывает все необходимые данные из Stream
и больше не нуждается в них, то я бы хотел, чтобы они были удалены.Если объект Foo
должен удерживать поток и использовать его в течение всего времени жизни, я бы не хотел, чтобы он был утилизирован.
Аналогично, как насчет экземпляров, которые извлекаются из чего-то другого, кроме конструктора, например Control.CreateGraphics()
.Эти экземпляры могут существовать вне кода, поэтому компилятор не будет их утилизировать автоматически.
Предоставление пользовательского элемента управления (и обеспечение идиомы, подобного блоку using
) проясняет намерение пользователя и значительно упрощает определение мест, где экземпляры IDisposable
не утилизируются должным образом.Если бы компилятор автоматически избавлялся от некоторых экземпляров, то отладка была бы намного сложнее, так как разработчику пришлось бы расшифровывать, как правила автоматического удаления применяются к каждому блоку кода, который использовал IDisposable
object.
Наконец, есть две причины (по соглашению) для реализации IDisposable
для типа.
- Вы используете неуправляемый ресурс (то есть вы делаетевызов P / Invoke, который возвращает что-то вроде дескриптора, который должен быть освобожден другим вызовом P / Invoke)
- В вашем типе есть экземпляры
IDisposable
, которые следует утилизировать, когда закончится время жизни этого объекта.
В первом случае все такие типы должны реализовывать финализатор, который вызывает Dispose
и высвобождает все неуправляемые ресурсы, если разработчику не удается это сделать (это предотвращаетутечки памяти и ручки).