Выдавание исключения от конструктора в.NET

Открыть терминал и выполнить команду:

open -n -a "Visual Studio"
11
задан Peter Mortensen 10 November 2011 в 23:04
поделиться

5 ответов

В общем, это безопасно с точки зрения предотвращения утечки памяти. Но создание исключений из конструктора опасно, если вы выделяете неуправляемые ресурсы в типе. Рассмотрим следующий пример

public class Foo : IDisposable { 
  private IntPtr m_ptr;
  public Foo() {
    m_ptr = Marshal.AllocHGlobal(42);
    throw new Exception();
  }
  // Most of Idisposable implementation ommitted for brevity
  public void Dispose() {
    Marshal.FreeHGlobal(m_ptr);
  }
}

. Этот класс будет пропускать память каждый раз, когда вы пытаетесь создать, даже если вы используете блок using. Например, утечка памяти.

using ( var f = new Foo() ) {
  // Won't execute and Foo.Dispose is not called
} 
25
ответ дан 3 December 2019 в 01:20
поделиться

Да, сборщик мусора освободит управляемые ресурсы, уже выделенные в объекте. Если вы инициализировали какие-либо неуправляемые ресурсы, вам нужно будет очистить их самостоятельно обычным способом.

2
ответ дан 3 December 2019 в 01:20
поделиться

Выброс исключений из конструктора должен быть нормальным, если вы не создали неуправляемых ресурсов. Однако, если вы действительно создаете неуправляемые ресурсы в конструкторе, все тело этого конструктора, включая выбросы, должно быть заключено в try / catch. Чтобы украсть отличный пример ДжаредПара:

public class Foo : IDisposable { 
  private IntPtr m_ptr;
  public Foo() {
    try
    {
        m_ptr = Marshal.AllocHGlobal(42);
        throw new Exception();
    }
    catch
    {
        Dispose();
        throw;
    }
  }
  // Most of Idisposable implementation ommitted for brevity
  public void Dispose() {
    Marshal.FreeHGlobal(m_ptr);
  }
}

Теперь будет работать следующее:

using ( var f = new Foo() ) {
  // Won't execute, but Foo still cleans itself up
}
10
ответ дан 3 December 2019 в 01:20
поделиться

Забавно, потому что я помогал с аналогичным вопросом только вчера.

Это более серьезная проблема, если у вас есть производный тип, потому что некоторые части производного типа будут инициализированы, но не другие. С точки зрения памяти это не имеет значения, потому что сборщик мусора знает, что где. Но если у вас есть какие-либо неуправляемые ресурсы (реализовать IDisposable), все может стать неясным.

4
ответ дан 3 December 2019 в 01:20
поделиться

Это зависит от того, какие еще ресурсы вы приобрели до того, как исключение будет устранено. Я не думаю, что создание исключений в конструкторе - это хорошо, но бросать их в финализаторы или dispose () намного хуже.

1
ответ дан 3 December 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: