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

发布于 2024-09-26 22:45:10 字数 412 浏览 9 评论 0原文

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

当主机应用程序使用许多这样的接口时,它期望处理可能发生的某些异常,例如 IDataRetriever 接口有一个方法 SomeDataType GetData(int timeout); 和主机可以处理一些自定义异常,例如 DataRetrievalTimeoutException 或 NetworkConnectionException。

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

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

I'm currently developing a solution and have designed it in a way such that it strongly implements the strategy/provider pattern. As such the solution exposes a number of interfaces and contains default implementations of these interfaces which can be replaced via a DI type methodology.

Where the host application uses a number of these interfaces it is expecting to handle certain exceptions that may occur, for example IDataRetriever interface has a method SomeDataType GetData(int timeout);and the host can handle some custom exceptions such as DataRetrievalTimeoutException or NetworkConnectionException.

My question is, what is the best way to mark up the interface class such that when a developer implements it they would know that certain exceptions should be thrown and would be handled by the host?

At the moment I have just added the exception xml tags to the methods xml comment - does this suffice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

守护在此方 2024-10-03 22:45:10

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

您可能需要查看代码契约,它可以让您使用契约注释您的界面,其中可以包括异常、先决条件ETC。

The XML tags (and any other documentation you want to write) are basically the closest you've got in "vanilla" .NET at the moment.

You might want to look at Code Contracts which lets you annotate your interface with contracts, which can include exceptions, preconditions etc.

是伱的 2024-10-03 22:45:10

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

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

You cannot in an interface. You CAN in a base class.

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

vs.

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);
}
丶视觉 2024-10-03 22:45:10

我建议在接口中定义异常类,并指定不从这些异常派生的任何异常都不应被允许逃逸,除非 CPU 着火或存在其他此类严重情况(即使如此,有一个显式定义的 IWoozle.SystemCorruptionException ,这样如果 Pokemon 处理程序只是捕获、记录并抛出异常,日志将反映出至少有人认为该异常很重要)。

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

I would suggest defining exception classes within the interface, and specifying that no exceptions which do not derive from those should be allowed to escape unless the CPU is on fire or other such drastic situation exists (even then, it might not be a bad idea to have an explicitly-defined IWoozle.SystemCorruptionException so that if a Pokemon handler simply catches, logs, and throws out the exception, the log will reflect that at least someone thought the exception was important).

I consider Microsoft's recommendation to avoid defining custom exception types to be unfortunate, since it means that there's no clean way to distinguish whether IEnumerator<T>.MoveNext() throws an InvalidOperationException because the underlying collection was altered during enumeration, or whether the internal processing of IEnumerator<T>.MoveNext() encounters an InvalidOperationException and simply lets it bubble up to the caller. If instead, IEnumerator<T>.MoveNext() threw an IEnumerator.InvalidatedEnumeratorException in the former case, then any InvalidOperationException which escaped would have to represent the latter case.

梦里梦着梦中梦 2024-10-03 22:45:10

这不应该由实现该接口的类决定吗?

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

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

Should this not be up to whatever class implements the Interface?

Eg if I take your Interface and implement my own class, with a method GetData, I could be 'getting' data from anywhere. Lets say it was a web service then the types of exceptions that could be thrown could be different to those if I was 'getting' data from local file system.

So in my implementation I would implement (and document) those exceptions specific to the implmentation so that whatever code is using the implementation could handle them. How those exception are handled may be very specific to the implementation, say I am consuming them in a web app as opposed to a desktop app.

偷得浮生 2024-10-03 22:45:10

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

I think the best way to provide this information is in the XML documentation that you would provide for each interface. There you can specify what Exception is thrown by the method so that the host can handle that error.

梦开始←不甜 2024-10-03 22:45:10

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

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

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

Another strategy if you can't support a generic base class, is extension method implementations.

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

This has the benefit of allowing you to not require an inheritance chain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文