#c# #dispose
#c# #утилизировать #dispose
Вопрос:
Предполагается, что у меня есть класс, подобный приведенному ниже:
public class DisposableClass : IDisposable()
{
private readonly Timer timer;
DisposableClass()
{
this.timer = new Timer(s => cb(s), s, 1000, 1000);
}
Init()
{
try
{
// Do some initialization here that is not done in ctor.
}
catch (Exception)
{
// Log error.
throw;
}
finally
{
// Is this correct?
this.Dispose();
}
}
public void Dispose()
{
this.timer?.Dispose();
}
}
Мой вопрос заключается в том, необходимо ли finally
предложение (или его вообще не должно быть) в приведенном выше случае для любого неконструкторного метода при генерировании необработанного исключения. Спасибо.
Редактировать:
В ответе, пожалуйста, рассмотрите проблемы в зависимости от уровней Init()
бытия public
, protected
, private
видимости.
Комментарии:
1. Я забыл упомянуть в вопросе о соображениях видимости. Обновлен вопрос.
2. Я думаю, что это может быть необязательно … поскольку вызов
Dispose
должен выполняться потребителем класса, а не самим классом… Я имею в виду, рассмотримusing()
блок, он компилируется вtry{} finally{}
блок … таким образом, даже при возникновении исключения он вызоветDispose
3. Я имею в виду, как потребитель API, я бы не ожидал, что какой-то экземпляр внезапно станет удаленным… Я думаю, что само удаление не должно быть обязанностью класса
4. Класс не несет ответственности за удаление собственного экземпляра. Однако, если вы вызываете
Init()
из конструктора, то не будет экземпляра, который кто-то мог бы вызватьDispose()
, тогда класс отвечает за удаление таймера, если он уже создан (не обязательно через вызовDispose()
, но через тоже нормально).5. Проблема с приведенным выше кодом для сценария, когда
Init
является общедоступным методом, заключается в непоследовательном поведении общедоступного контакта. Обычно ожидается, что ваш экземпляр находится в состоянии готовности к использованию сразу после его создания. Если вы разбиваете инициализацию на разные этапы и этим нарушаете ее атомарность, вы создаете потенциальные проблемы с потреблением: возможность полуинициализированного состояния, условия гонки и т.д. Выполняя все необходимые действия по инициализации в конструкторе, вы в основном избегаете этих проблем и не должны беспокоиться о дополнительном удалении при сбое инициализации.