Следует ли вызывать Dispose при повторном перемещении необработанного исключения?

#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 является общедоступным методом, заключается в непоследовательном поведении общедоступного контакта. Обычно ожидается, что ваш экземпляр находится в состоянии готовности к использованию сразу после его создания. Если вы разбиваете инициализацию на разные этапы и этим нарушаете ее атомарность, вы создаете потенциальные проблемы с потреблением: возможность полуинициализированного состояния, условия гонки и т.д. Выполняя все необходимые действия по инициализации в конструкторе, вы в основном избегаете этих проблем и не должны беспокоиться о дополнительном удалении при сбое инициализации.