Начните с этих простых классов...
Скажем, у меня есть простой набор таких классов:
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 имеет два Shoe s, каждый Shoe имеет Shoelace. Все очень глупо.
Добавить объект IDisposable к Shoelace
Позже я решил, что некоторые операции с 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 без необходимости Dispose(bool) и Destructor:
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 spreads
Правильно, что это исправлено. Но теперь FxCop будет жаловаться, что Shoe создает Shoelace, поэтому Shoe тоже должен быть IDisposable.
И Driver создает Shoe, поэтому Driver должен быть IDisposable.
И Bus создает Driver, поэтому Bus должен быть IDisposable и т.д.
Неожиданно мое небольшое изменение на Shoelace вызывает у меня много работы, и мой босс задается вопросом, почему мне нужно проверить Bus, чтобы внести изменения в Shoelace.
Вопрос
Как вы предотвращаете это распространение IDisposable, но все же убедитесь, что неуправляемые объекты правильно расположены?