Начните с этих простых занятий ...
Скажем, у меня есть простой набор таких классов:
class Bus
{
Driver busDriver = new Driver();
}
class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}
class Shoe
{
Shoelace lace = new Shoelace();
}
class Shoelace
{
bool tied = false;
}
A Busимеет a Driver, Driverимеет два Shoes, каждый Shoeимеет a Shoelace. Все очень глупо.
Добавить объект IDisposable в шнурки
Позже я решил, что некоторые операции над объектом Shoelaceмогут быть многопоточными, поэтому я добавляю, EventWaitHandleчтобы потоки взаимодействовали с ним. Итак, Shoelaceтеперь это выглядит так:
class Shoelace
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
// ... other stuff ..
}
Реализуйте IDisposable на шнурках
Но теперь Microsoft FxCop будет жаловаться: «Реализуйте IDisposable на« Shoelace », потому что он создает элементы следующих типов IDisposable:« EventWaitHandle ».
Хорошо, я реализую IDisposableна Shoelaceи мой аккуратный класс немного становится этим ужасным беспорядком:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Shoelace()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
}
// No unmanaged resources to release otherwise they'd go here.
}
disposed = true;
}
}
Или (как указано комментаторами), поскольку Shoelaceсам по себе не имеет неуправляемых ресурсов, я мог бы использовать более простую реализацию удаления без необходимости использования Dispose(bool)и Деструктора:
class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
public void Dispose()
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
GC.SuppressFinalize(this);
}
}
С ужасом наблюдайте, как IDisposable распространяется
Правильно, это исправлено. Но теперь FxCop будет жаловаться на то, что Shoeсоздает Shoelace, значит Shoe, IDisposableтоже.
И Driverтворит Shoeтак и Driverдолжно быть IDisposable. И Busтворит Driverтак Busдолжно быть IDisposableи так далее.
Внезапно мое небольшое изменение в Shoelaceвызывает у меня много работы, и мой босс задается вопросом, почему мне нужно Busоформить заказ, чтобы внести изменения Shoelace.
Вопрос
Как предотвратить такое распространение IDisposable, но при этом обеспечить правильную утилизацию неуправляемых объектов?