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