Как реализации интерфейса должны обрабатывать неожиданные внутренние исключения типов, которые могут ожидать вызывающие? - PullRequest
2 голосов
/ 13 июля 2011

Если класс реализует интерфейс, как он должен обрабатывать ситуации, в которых

  1. При выполнении метода или свойства возникает внутренняя ошибка, которая имеет тип, который вызывающая сторона может ожидатьсправиться, но который звонящий, возможно, не должен.Например, IDictionary.Add внутренне что-то делает, что выдает ArgumentException при обстоятельствах, которые подразумевают, что словарь поврежден, но не будет ли означать что-либо плохое в остальной части системы?Или они подразумевают, что что-то испорчено за пределами словаря?Вызывающая сторона может ожидать, что поймает и обработает тот факт, что дублирующий ключ существует в словаре, поскольку в некоторых случаях исключение может быть Vexing (например, один и тот же код может использоваться для словаря, к которому нет доступа другими потоками, и для ConcurrentDictionaryчто, и семантика была бы работоспособна, если попытка добавить дублирующую запись вызвала чистый сбой).Разрешение perguate ArgumentException приведет к тому, что вызывающая сторона будет верить, что словарь находится в том же состоянии, как если бы никогда не происходило добавление, что может быть опасно, но создание другого типа исключения может показаться запутанным.
  2. При выполнении метода или свойства возникает исключение, которое, возможно, должен или не должен обрабатывать вызывающий объект, и определение интерфейса не дает никаких намеков на то, что может произойти любое даже удаленно связанное исключение.Например, предположим, что что-то идет не так в оценке IEnumerator, либо подразумевает (1), что перечислитель был поврежден (возможно, из-за непредвиденных действий в другом потоке), но повторная попытка перечисления может быть успешной;(2) сам перечисляемый объект, вероятно, поврежден или непригоден для использования, но все остальное в системе, вероятно, в порядке (например, процедура анализа файла, обработанная лениво, ударила по недопустимой записи);(3) что-то за пределами перечисляемого объекта было повреждено.IEnumerable имеет только одно определенное исключение, которое он может выдать, но вызывающая сторона может захотеть изменить свое действие в зависимости от «серьезности» исключения.
Если бы у меня были мои детекторы, система определяла бы некоторые типы, такие как RetryableFailureException, CleanFailureException, ObjectCorruptFailureException, и большинству интерфейсов было бы разрешено выбрасывать эти или их производные.Поскольку дело обстоит не так, как следует правильно обрабатывать интерфейсы, либо с точки зрения интерфейса, либо с точки зрения вызывающего абонента?

Кстати, один шаблон, который я не видел реализованным, но который может показаться полезным, был бы для методовпринять параметр делегата, который будет выполнен в случае сбоя метода таким образом, что метод «try» вернет false.Такой делегат, предоставленный вызывающей стороной, мог бы затем не только генерировать исключение, которое получатель будет знать искать, но также мог устанавливать флаг, который в противном случае был бы доступен только вызывающей стороне.Таким образом, вызывающий абонент мог знать, что обнаруженное исключение действительно было ожидаемым.

1 Ответ

0 голосов
/ 27 июля 2011

Работа интерфейса заключается в определении членов (и их подписей), которые должен иметь класс, а не того, как они должны быть реализованы.Поэтому я бы сказал, пусть исключение всплывает в стеке.Если вы действительно хотите определить контракт и контролировать некоторые из реализаций (например, обработку ошибок), то вам следует создать базовый класс (в данном случае я бы склонялся к классу MustInherit / Abstract) с методами MustOverride, которые базовый класс вызывает изего методы (в вашей ситуации в Try Catch, чтобы вы могли выполнять свою специальную обработку ошибок).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...