Как указать исключения, которые будут выброшены разработчиком интерфейса? - PullRequest
15 голосов
/ 13 октября 2010

В настоящее время я разрабатываю решение и спроектировал его таким образом, чтобы оно решительно реализовало шаблон стратегии / провайдера.Как таковое решение предоставляет ряд интерфейсов и содержит реализации этих интерфейсов по умолчанию, которые могут быть заменены с помощью методологии типа DI.

Когда хост-приложение использует ряд этих интерфейсов, оно ожидает обработки определенных исключенийможет возникнуть, например, IDataRetriever интерфейс имеет метод SomeDataType GetData(int timeout);, и хост может обрабатывать некоторые пользовательские исключения, такие как DataRetrievalTimeoutException или NetworkConnectionException.

Мой вопрос: каков наилучший способ разметки класса интерфейса, чтобы, когда разработчик реализовывал его, он знал, что определенные исключения должны быть выданы и обрабатываться хостом?

В данный момент я только что добавил xml-теги исключений в комментарии XML-методов - этого достаточно?

Ответы [ 6 ]

12 голосов
/ 13 октября 2010

XML-тэги (и любая другая документация, которую вы хотите написать) в настоящее время являются наиболее близкими к вам в «vanilla» .NET.

Возможно, вы захотите взглянуть на КодКонтракты , которые позволяют аннотировать ваш интерфейс контрактами, которые могут включать исключения, предварительные условия и т. Д.

2 голосов
/ 02 февраля 2012

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

Я считаю, что рекомендация Microsoft избегать определения пользовательских типов исключений вызывает сожаление, поскольку это означает, что нет никакого чистого способа определить, выбрасывает ли IEnumerator<T>.MoveNext() значение InvalidOperationException, потому что базовая коллекция была изменена во время перечисления, или внутренняя обработка из IEnumerator<T>.MoveNext() встречает InvalidOperationException и просто позволяет ему всплывать до звонящего. Если вместо этого IEnumerator<T>.MoveNext() бросил IEnumerator.InvalidatedEnumeratorException в первом случае, то любой сбежавший InvalidOperationException должен был бы представлять второй случай.

2 голосов
/ 13 октября 2010

Вы не можете в интерфейсе.Вы МОЖЕТЕ в базовом классе.

public interface IFoo
{    
  /// <summary>
  /// Lol
  /// </summary>
  /// <exception cref="FubarException">Thrown when <paramref name="lol"> 
  /// is <c>null</c></exception>
  /// <remarks>Implementors, pretty please throw FE on lol 
  /// being null kthx</remarks>
  void Bar(object lol);
}

против

public abstract BaseFoo
{    
  /// <summary>
  /// Lol
  /// </summary>
  /// <exception cref="FubarException">Thrown when <paramref name="lol"> 
  /// is <c>null</c></exception>
  public void Bar(object lol)
  {
    if(lol == null)
      throw new FubarException();
    InnerBar(lol);
  }

  /// <summary>
  /// Handles execution of <see cref="Bar" />.
  /// </summary>
  /// <remarks><paramref name="lol"> is guaranteed non-<c>null</c>.</remarks>
  protected abstract void InnerBar(object lol);
}
1 голос
/ 02 февраля 2012

Разве это не может зависеть от того, какой класс реализует Интерфейс?

Например, если я возьму ваш Интерфейс и реализую свой собственный класс, с помощью метода GetData я мог бы "получать" данные из любого места.Допустим, это был веб-сервис, тогда типы исключений, которые могли бы генерироваться, могли бы отличаться от тех, которые я получал бы из локальной файловой системы.

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

0 голосов
/ 13 октября 2010

Другая стратегия, если вы не можете поддерживать базовый базовый класс, это реализации метода расширения.

public static void ThisMethodShouldThrow(this Iinterface obj)
{
     if(obj.ConditionToThrowIsMet) throw new...
}

Это позволяет вам не требовать цепочки наследования.

0 голосов
/ 13 октября 2010

Я думаю, что лучший способ предоставить эту информацию - это документация XML, которую вы предоставляете для каждого интерфейса.Там вы можете указать, какое исключение выдает метод, чтобы хост мог обработать эту ошибку.

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