Обычно отказ от вызова Dispose указывает на возможную ошибку или небрежный код и может привести к трудностям для поиска ошибок. В идеале я хотел бы заметить, не вызывается ли Disposed во время модульных тестов.

Один из методов, который мы использовали, заключался в том, чтобы поместить Debug.Assert в Finalizer.

#if DEBUG
~MyClass()
{
    Debug.Assert(false, “MyClass.Dispose() was not called”);
}
#endif

И мы обнаружили, что щелкаем по окнам сообщений assert, но это не работало с сборками непрерывной интеграции, которые игнорировали всплывающие окна.

2
smvlad 26 Мар 2009 в 21:06
Кстати. вы можете использовать Debug.Fail (...) вместо Debug.Assert (false, ...)
 – 
tanascius
26 Мар 2009 в 21:09

3 ответа

Лучший ответ

Если вы каким-то образом регистрируете это вместо использования Debug.Assert и используете инъекцию зависимостей, чтобы указать реализацию вашего регистратора, вы можете использовать имитационное тестирование, чтобы поймать это. Итак, ваш класс может принять экземпляр регистратора в своем конструкторе или предоставить экземпляр по умолчанию, а затем вести себя следующим образом:

public MyClass : IDisposable
{

IEventLogger _eventLogger;

public MyClass() : this(EventLogger.CreateDefaultInstance())
{
}

public MyClass(IEventLogger eventLogger)
{
    _eventLogger = eventLogger;
}

// IDisposable stuff...

#if DEBUG
~MyClass()
{
    _eventLogger.LogError("MyClass.Dispose() was not called");
}
#endif

}
3
David M 26 Мар 2009 в 21:22

Для обнаружения этой проблемы можно написать правило fxCop.

Кроме того, проверка того, что все виды использования IDisposable используются внутри блока using {}, значительно упрощает решение этой проблемы.

Правило, которое я проверил, для ручных вызовов Dispose () или использования using {}

Ручные вызовы для удаления, конечно, труднее обнаружить во всех ситуациях, поскольку могут существовать управление потоком или исключения, которые могут препятствовать возникновению вызова.

0
Jason Coyne 27 Мар 2009 в 00:15

Вы можете использовать объектную структуру Mock (например, RhinoMocks), чтобы убедиться, что вызывается IDisposable.Dispose (). Если Dispose () не был вызван, фреймворк автоматически завершит сборку.

0
Michael Larionov 27 Мар 2009 в 22:00