Другие ответы о сбое питания, Environment.FailFast()
, итераторах или мошенничестве с помощью using
чего-то, что является null
, все интересны.Но мне кажется любопытным, что никто не упомянул о том, что, на мой взгляд, является наиболее распространенной ситуацией, когда Dispose()
не будет вызываться даже при наличии using
: когда выражение внутри using
выдает исключение.
Конечно, это логично: выражение в using
вызвало исключение, поэтому присвоение не состоялось, и нет ничего, что мы могли бы назвать Dispose()
.Но одноразовый предмет уже может существовать, хотя он может быть в полуинициализированном состоянии.И даже в этом состоянии он уже может содержать некоторые неуправляемые ресурсы.Это еще одна причина, почему важно правильно реализовать одноразовый шаблон.
Пример проблемного кода:
using (var f = new Foo())
{
// something
}
…
class Foo : IDisposable
{
UnmanagedResource m_resource;
public Foo()
{
// obtain m_resource
throw new Exception();
}
public void Dispose()
{
// release m_resource
}
}
Здесь, похоже, Foo
правильно выпускает m_resource
, и мыиспользуя using
тоже правильно.Но Dispose()
на Foo
никогда не вызывается из-за исключения.Решением в этом случае является использование финализатора и освобождение ресурса там.