16

我目前正在开发一个解决方案,并以一种能够强有力地实现策略/提供者模式的方式对其进行设计。因此,该解决方案公开了许多接口并包含这些接口的默认实现,这些接口可以通过 DI 类型方法进行替换。

在宿主应用程序使用许多这些接口的地方,它期望处理可能发生的某些异常,例如IDataRetriever接口有一个方法SomeDataType GetData(int timeout);,宿主可以处理一些自定义异常,例如DataRetrievalTimeoutExceptionNetworkConnectionException

我的问题是,标记接口类的最佳方法是什么,这样当开发人员实现它时,他们会知道应该抛出某些异常并由主机处理?

目前,我刚刚将异常 xml 标记添加到方法 xml 注释中 - 这是否足够?

4

6 回答 6

13

XML 标记(以及您想要编写的任何其他文档)基本上是您目前在“vanilla”.NET 中获得的最接近的标记。

您可能想查看代码合同,它可以让您使用合同注释您的界面,其中可以包括异常、先决条件等。

于 2010-10-13T11:50:50.400 回答
3

您不能在界面中。您可以在基类中。

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);
}
于 2010-10-13T12:09:19.270 回答
2

我建议在接口中定义异常类,并指定除非 CPU 着火或存在其他此类极端情况,否则不应允许不从这些类派生的异常逃逸(即使那样,这样做可能不是一个坏主意有一个明确定义的IWoozle.SystemCorruptionException,这样如果口袋妖怪处理程序只是捕获、记录并抛出异常,日志将反映至少有人认为异常很重要)。

我认为微软避免定义自定义异常类型的建议是不幸的,因为这意味着没有明确的方法来区分是否IEnumerator<T>.MoveNext()抛出一个,InvalidOperationException因为底层集合在枚举期间被更改,或者内部处理是否IEnumerator<T>.MoveNext()遇到一个InvalidOperationException并简单地让它冒泡给来电者。相反,如果在前一种情况下IEnumerator<T>.MoveNext()抛出一个,那么任何逃脱的都必须代表后一种情况。IEnumerator.InvalidatedEnumeratorExceptionInvalidOperationException

于 2012-02-02T16:55:25.033 回答
1

这不应该取决于实现接口的任何类吗?

例如,如果我使用您的接口并使用 GetData 方法实现我自己的类,我可以从任何地方“获取”数据。假设它是一个 Web 服务,那么如果我从本地文件系统“获取”数据,那么可能引发的异常类型可能会有所不同。

因此,在我的实现中,我将实现(并记录)那些特定于实现的异常,以便使用该实现的任何代码都可以处理它们。如何处理这些异常可能非常具体到实现,比如我在 Web 应用程序而不是桌面应用程序中使用它们。

于 2012-02-02T05:19:33.870 回答
0

我认为提供此信息的最佳方式是在您将为每个接口提供的 XML 文档中。您可以在此处指定该方法引发的异常,以便主机可以处理该错误。

于 2010-10-13T11:54:03.887 回答
0

如果您不能支持通用基类,另一种策略是扩展方法实现。

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

这样做的好处是允许您不需要继承链。

于 2010-10-13T13:09:27.833 回答