可以强制开发人员处理特定的异常吗?

时间:2011-05-18 16:28:46

标签: c# .net exception programming-languages interface

基本上,我想要一种特殊形式的Interface用于例外,它要求任何使用我的对象的人用特定的catch实现来包装它。

示例

我有一个将数据发送到另一台主机的对象。我希望现实的实现需要一种方法来处理以下异常:

  • HostNotFoundException
  • InvalidUsernameException
  • AccountExpiredException
  • DataAlreadyExistsException

类似于如何使用InterfaceAbstract类强制在派生类中创建方法和属性,有什么方法可以强制消费者以我期望的方式实现异常处理?

在类似的说明中,我还想强制方法(通过Interface或Abstract创建)能够生成某些异常。当然它们可能未实现,但我想告诉开发人员(不阅读文档)应该考虑它们。

目标

此异常检查的好处是可以实现更强大的错误处理。这将由消费者使用对象和对象创建者来完成。

解决方案吗

我能想到的唯一方法是T4模板,但这并不像我想的那样完整。我很乐意看到这种语言本身实现了。

3 个答案:

答案 0 :(得分:7)

除了跳过篮球之外,你不能强迫程序员做任何事情。例如,假设您有一些名为Frob的方法可以执行某些操作,并且可以抛出FrobinatorException。你希望程序员写:

try
{
    var result = Frob(foo);
}
catch (FrobinatorException)
{
    // handle exception here
}

但你发现他们没有。因此,通过这样定义Frob来强迫他们:

public FrobResult Frob(FrobyThing foo, Action FrobinatorExceptionHandler);

然后程序员必须编写如下内容:

var result = Frob(
    foo, 
    () => { /* handle FrobinatorException here */; });

程序员会抱怨不得不这样做,他们最终会写这个:

var StupidExceptionHandler = new Action(() => {});
var result = Frob(foo, StupidExceptionHandler);

现在你的情况比你更糟糕,因为被吞没的例外,这隐藏了错误。如果程序员完全忽略异常处理,那就更好了。至少这种方式你知道什么时候发生错误。

没有办法强制进行良好的异常处理。至少,不是在目前存在的C#中。您可以更方便地处理异常,但这样做通常可以通过吞噬异常来更容易地隐藏异常。

答案 1 :(得分:2)

如果我正确地阅读了你的问题,听起来好像你正在寻找已检查的例外情况。从C#开发的早期开始有一个interesting article,实际上讨论了这个问题。

从设计的角度来看,我并没有真正看到你如何“强迫”接口的使用者来处理你的异常。毕竟,你怎么知道它正在被处理?调用您的接口的方法是否需要直接将该调用包装在try/catch中?或者,调用 方法的方法是否足够?或者为应用程序执行全局异常处理程序?实际上应该由接口的使用者决定如何/何时/何处理异常。

您可以采取的最佳方法是记录界面上intellisense评论中的潜在异常。但这会带来一个有趣的问题,你也提到(如果我正确地读你)。这里的问题是文档在界面上,而不是在实现上。如果一个或多个实现抛出与接口所期望的异常不同的异常怎么办?

总的来说,我认为这里要达到的平衡仍然是记录界面上的潜在异常。您给出的四个示例听起来像一个接口的安全假设来实现它的实现。但这取决于接口方法接受什么作为参数。

例如,如果“主机”或“用户名”的整个概念完全封装在实现中(例如从某种服务接口中访问Web服务,这可能很容易打到数据库或在其他/后期实现中的一些其他记录源)然后关于那些数据的异常在接口级别上没有意义。在这种情况下,最好创建一个异常类型,如“DomainException”或“ImplementationException”或“DataRetrievalException”或类似的东西,只是将内部实现细节放在异常中。

然而,回到主要观点......从接口和对象的角度来看,您不应该关心消费者如何处理异常。你应该做的只是在内部处理任何有意义的内部处理和抛出有意义抛出的异常。除此之外的任何事物都会在消费者和组件之间产生耦合。

答案 2 :(得分:2)

虽然我部分同情你更好的错误处理的目标,但我觉得如果你强迫你的代码的消费者正确处理异常,那么你的同事会在检查它的20分钟内谋杀你。

由于C#缺少检查异常,因此您可以减少记录代码,以便消费者了解期望的内容以及期望的条件。

另一方面,ReSharper有一个名为Exceptional的好插件,可以识别代码中您未处理可能异常的位置,或者没有记录,因此调用者可以这样做。