Да, вы должны реализовать IDisposable
в каждом классе, в котором есть член, реализующий IDisposable
. Смотри http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=VS.100).aspx.
Однако реализация IDisposable
просто обеспечивает своевременную очистку ресурсов. Как правило, отказ от реализации IDisposable
не приведет к длительной утечке памяти, поскольку сборщик мусора в конечном итоге сможет запустить финализаторы, которые освободят ресурсы операционной системы. Но отсутствие утилизации может привести к кратковременным утечкам памяти и истощению ресурсов. может вызывать долговременные проблемы, но это довольно редко встречается при работе с объектами BCL.
Например, в приведенной выше тестовой программе созданные вами объекты Leaking
становятся «без корневыми» после выхода из цикла, и, как вы видели, сборщик мусора действительно собирает их. Если вы позволите вашей программе работать некоторое время, занимаясь другими делами, эти объекты будут собраны во время следующей сборки мусора. Это кратковременная утечка памяти и ресурсов, но не долгосрочная проблема.
Теперь вы можете столкнуться с утечкой памяти, если у вас что-то вроде:
FileSystemWatcher watcher = new FileSystemWatcher(...);
void MakeABigLeak()
{
for (int i = 0; i < 10; ++i)
{
var MyObject = new SomeObject();
watcher.Changed += MyObject.ChangeHandler;
}
}
В этом случае watcher
содержит ссылку на каждый из созданных объектов. И поскольку watcher
является корнем, эти объекты останутся активными. Они не будут собирать мусор.
Единственный способ исправить это - убедиться, что объект удаляется из уведомления о событии. Вы можете сделать это в методе Dispose
объекта, хотя есть и другие способы. Однако вы должны быть осторожны , а не , чтобы сделать это в финализаторе. Помните, что финализаторы работают без установленного порядка. Возможно, что watcher
было завершено до объекта, который ссылается на него (поскольку ни один из них не является корневым, порядок завершения не имеет значения). Вот почему существует метод Dispose(bool)
: для предотвращения доступа к другим объектам во время финализации.
Это ваш выбор. Вы можете написать метод Dispose
, который удаляет объект из уведомления о событии, или вы можете быть уверены, что напишите код, который выполняет удаление, когда объект больше не заинтересован в событии. Недостатком этого в Dispose
является то, что объект, выполняющий подписку, должен поддерживать ссылку на объект, который вызывает события.