У меня есть пара наблюдений.
Во-первых, не создавайте исключения из Dispose. На самом деле, я бы даже сказал, что никогда не скажу никогда. Разработчики .NET были уверены, что Dispose всегда будет успешным и по уважительной причине. Было бы неудобно помещать вызов в try-catch каждый раз, и это, безусловно, уменьшило бы читаемость.
Во-вторых, и это часто обсуждается, избегайте создания исключений из конструкторов. Исключения, связанные с проверкой состояния, такие как ArgumentException или IndexOutOfRangeException, допустимы, поскольку они обычно генерируются из-за нарушений предварительных условий и обычно являются результатом ошибки программирования. Но непредсказуемые исключения, такие как SqlException, в значительной степени вынудили бы вызывающую программу обернуть конструктор в блок try-catch. Опять же, это приводит к неудобным сценариям кодирования. Но, что более важно, это может привести к незначительным утечкам ресурсов в сценариях, когда конструктор выделяет неуправляемые ресурсы, а затем выдает исключение перед возвратом нового экземпляра вызывающей стороне. Без ссылки на экземпляр вызывающая сторона не может вызвать Dispose.