C#和asp.net错误处理最佳实践?

时间:2011-04-02 08:40:12

标签: c# .net asp.net c#-3.0 c#-2.0

  

可能重复:
  Best practices for exception management in JAVA or C#

我正在使用类库,我尝试在类库中放入最多代码,以便可以在其他项目中重用它。

请告诉我应该在类库函数或前端表单(aspx页面)中放置try catch块?

请分享处理错误的最佳做法。

3 个答案:

答案 0 :(得分:2)

回答完全到你要求的内容,try-catch块用于处理异常,所以你应该把它们放在你真正想要的地方处理异常

这可能有点微妙,所以让我举一些例子:假设您有一些方法可以对文件执行某些操作,并且文件的路径是作为参数给出的。在这种情况下可能会发生许多不好的事情:

如果找不到文件,或者无法打开文件(例如:权限问题,被某些进程阻止等),那么它就是调用者而不是被调用者的错,并且产生的异常已经是问题描述:让它传播。

如果文件不是预期的格式(例如,你得到一些int.Parse()调用失败,因为应该有一个数字但是没有),它仍然是调用者的错(它传递给你一条路径一个坏文件,多么意思!),但内部异常不准确的问题;这里catch-wrap-throw模式效果最好:你捕获异常,包装成更具描述性的异常类型(即,创建一个好类型的新异常,并将旧的异常放入其中) InnerException),并抛出那个:调用者不关心代码中的哪个任务失败,它应该关心它失败的原因。

现在,让我们在最后一种情况下稍微调整一下场景:让我们假设您的库试图在预定义的位置读取一些可选的配置文件。如果加载其中任何一个失败,则该异常应该由库本身处理,回退到使用默认选项或其他。

总结:如果异常是调用者做错事的直接后果,那就让它传播。如果这是间接后果(例如,将路径传递给错误的文件),请使用catch-wrap-rethrow告诉调用者它做错了什么,而不是它如何破坏了代码的逻辑。如果这是一个你能够处理的不寻常但可预见的条件的信号,那么你只需处理它。除此之外,您可以在某些方法的开头进行一些“健全性检查”,并在知道某些参数值 会导致问题时预防性地抛出描述性异常而不是等待实际出现的麻烦(因此,当问题可以及早发现时,这是catch-wrap-rethrow的替代方案。)

回到客户端代码(使用API的代码),应该 ASAP 处理异常。从字面上理解:尽快,但实际上不可能。例如,一个函数作为另一个函数的包装器(“自制”咖喱)不应该尝试处理由它传递的参数触发的异常,除非它可以实际修复问题并重试。示例(非常通用):

void DoSomethingEasily(object someArgument) {
    MyAPI.DoSomething(someArgument, "some-predefined-string-argument");
}
// ... somewhere else on the code ...
    DoSomethingEasily(myObject);

在这种情况下,处理来自MyAPI.DoSomething的异常可能是一项拆分工作:如果异常是由"some-predefined-string-argument" 单独引起的,则它是DoSomethingEasily'处理它的工作。如果异常是由myObject引起的,则DoSomethingEasily不应该搞乱,让外部代码处理自己的麻烦。

如果存在一些不是由参数引起的异常(例如,由某些API状态或设备故障等外部因素引起),则 ASAP 的想法再次适用:如果DoSomethingEasily有足够的信息/背景来处理这些情况,那么肯定应该。但是,如果它不能,那么最好不要妨碍它,以便调用它的代码有机会处理这个问题。


奖金建议:无论案例(原因)如何, 您的API引发的任何异常都应始终记录在案 。如果您将C#与Visual Studio IDE一起使用,那么建议使用内置的XML注释文档格式,因此异常(及其描述)将显示在Intellisense的工具提示中。

希望这有帮助。

答案 1 :(得分:0)

Exceptin处理是一种机制,可防止从一种方法到另一种方法的结果(坏)结果,并将异常与结果隔离开来。

例如,您可以从UI调用类库(名为A)的方法,然后A调用B和B调用C.现在C方法中存在运行时问题(运行时异常)。你可以把东西归还给B然后说嘿!这里有一个错误,那么B也应该为A和A做同样的上层... 你看!你可以在C中抛出一个异常然后你不需要在B中捕获它。然后你只需要在一些上层调用A方法时放一个try-catch块,然后简单地报告错误而不需要添加任何额外的声明。当然,在某些情况下你必须将try-catch块放在类库中(例如,当你遇到一个只涉及你的类库而不是更高层的异常时)。

根据我的经验,捕获物应放置在最近的UI位置,您可以在其中以良好和最小的方式报告它。因此,“throw语句”应该不仅仅是类库中的“catch语句”。

当然,您可以实现自己的异常类,以便更好地处理错误(请参阅here)。

答案 2 :(得分:0)

并且在与外部服务交谈时也应该“仅”使用try / catch,在外部服务中您无法控制结果。否则,当你有控制权时,你应该避免引起异常,并且在没有对象可用的情况下采用“返回空”方法等。只是一个设计提示;)