繁体   English   中英

如何指定接口的实现者抛出的异常?

[英]How to specify exceptions to be thrown by an implementor of an interface?

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

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

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

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

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

您可能希望查看代码约定 ,它允许您使用合同注释您的接口,其中包括异常,前置条件等。

你不能在一个界面。 你可以在基类。

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);
}

我建议在接口中定义异常类,并指定除非CPU处于激烈状态或存在其他如此剧烈的情况,否则不应允许任何不从那些派生的异常转义(尽管如此,它可能不是一个坏主意有一个显式定义的IWoozle.SystemCorruptionException这样如果一个Pokemon处理程序只是捕获,记录并抛出异常,日志将反映出至少有人认为异常是重要的)。

我认为Microsoft的建议是避免定义自定义异常类型是不幸的,因为这意味着没有干净的方法来区分IEnumerator<T>.MoveNext()抛出InvalidOperationException因为枚举期间底层集合被更改,或者是否内部处理IEnumerator<T>.MoveNext()遇到InvalidOperationException ,只是让它冒泡到调用者。 相反, IEnumerator<T>.MoveNext()在前一种情况下抛出了IEnumerator.InvalidatedEnumeratorException ,然后任何转义的InvalidOperationException都必须代表后一种情况。

这不应该由任何类实现接口吗?

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM