如果我有一个接口,我会添加注释以识别将抛出特定异常,是否可以实现类来抛出不同的异常?
一个(不好)的例子是:
public interface IWidgetWorker {
/// <summary>
/// Do the work required for the specified work id.
/// </summary>
/// <param name="workId">The id of the piece of work to do</param>
/// <exception cref="ArgumentException">Thrown if workId is empty</exception>
public void DoWork(Guid workId);
}
public class DatabaseWidgetWorker : IWidgetWorker {
public void DoWork(Guid workId) {
// throw some database related exception
}
}
public class WebWidgetWorker : IWidgetWorker {
public void DoWork(Guid workId) {
// throw some web related exception
}
}
也许我添加WidgetWorkerException
课程?我在哪里记录实现类可能抛出的具体异常?
答案 0 :(得分:3)
界面设计的一部分通常记录预期的异常。这些异常在创建接口时是合乎逻辑的,例如,当调用方法且对象处于错误状态时为InvalidOperationException
,或者在传递不正确参数时为ArgumentOutOfRangeException
。
但是,接口可以通过多种方式实现。实现完全有可能查看文件系统或调用数据库,引入一系列在定义接口时无法预见的异常。
您想要知道方法抛出特定异常的唯一原因是能够以不同于一般异常处理的方式处理该条件。当您通过接口进行呼叫时,您将对接口进行编码而不是实现。您无法知道实现如何工作,因此无法以任何特定方式处理异常。您必须回退到更常见的异常处理。
经验法则应该是记录在暴露的接口下合理的异常,但是你应该期望一个实现抛出超出这些异常的异常。强大的代码将具有以通用方式处理这些未知异常的机制。
答案 1 :(得分:0)
实现类应该只抛出接口中指定的异常。如果接口没有提供报告错误的可能性,那么接口设计不当或者实现者应该将其搞砸,因为接口用户确实并不关心。
答案 2 :(得分:0)
这可能是主观的。我的感觉是实现类应该抛出当时自然抛出的异常。接口不声明允许哪些异常,哪些异常不允许。编译器不会查看您的注释,并且类可以抛出其他异常,仍然是您的接口的有效实现。
如果出于某种原因需要将这些异常设置为单一类型,那么无论在哪里调用IWidgetWorker.DoWork,您都可以捕获它们并使用原始内容异常重新抛出它们。
workId为空的情况可以在调用进入实现之前处理,因此没有理由不同的实现应该处理相同的检查和抛出ArgumentException。
在其他编程环境中可能会有所不同。我认为必须在某些语言中声明可能的异常,但不是在这里。
您的界面文档可以说明如何解释各种异常以及消费代码将执行的操作。如果异常是这样的话,消费代码可能会在一段时间间隔后再次尝试,但在其他情况下会终止报告错误。