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

发布于 2024-10-28 12:06:37 字数 333 浏览 5 评论 0原文

可能的重复:
JAVA 或 C# 中异常管理的最佳实践 < /p>

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

请建议我应该将 try catch 块放在类库函数或前端表单(aspx 页面)中的哪里?

还请分享处理错误的最佳实践。

Possible Duplicate:
Best practices for exception management in JAVA or C#

I am using class libraries and I try to put maximum code in class libraries so that it can be reused in other projects.

Please advice me where I should put try catch blocks in class library functions or in front end forms (aspx pages) ?

Kindly also share what are best practices for handling errors.

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

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

发布评论

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

评论(3

罪#恶を代价 2024-11-04 12:06:37

准确地回答您的问题,try-catch块用于处理异常,因此您应该将它们放在您想要的位置实际上正在处理异常

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

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

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

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

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

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

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

在这种情况下,处理来自 MyAPI.DoSomething 的异常可以是一项拆分工作:如果异常是由 “some-predefined-string-argument” 引起的code> 单独,那么就由 DoSomethingEasily 来处理它。如果异常是由 myObject 引起的,那么 DoSomethingEasily 不应该搞砸,让外部代码处理自己的麻烦。

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


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

希望这有帮助。

Answering exactly to what you are asking, try-catch blocks are used to handle exceptions, so you should put them where you will actually be handling the exception.

This can be a bit subtle, so let me put some example: imagine you have some method to do something with a file, and the path to the file is given as an argument. There may happen many bad things on that situation:

If the file can't be found, or it can't be open (ex: permissions issues, blocked by some procoess, etc), then it's the caller's and not the callee's fault, and the exception produced is already a description of the problem: let it propagate.

If the file is not in the expected format (for example, you get some int.Parse() calls failing because there should be a number but there isn't), it's still the caller's fault (it passed you a path to a bad file, how mean!), but the inner exception is not accurate of the problem; here the catch-wrap-throw pattern works best: you catch the exception, wrap it into a more descriptive exception type (ie, create a new exception of the good type, and put the old one as it's InnerException), and throw that one: the caller doesn't care about which task within your code failed, it should care about why it failed.

Now, let's tweak the scenario a bit for the last case: let's assume your library tries to read some optional configuration files, at a pre-defined location. If loading any of these fails, the exception should be handled by the library itself, falling back to using the default options or whatever.

In summary: if the exception is a direct consequence of the caller doing something wrong, let it propagate. If it's an indirect consequence (for example, passing the path to the wrong file), use catch-wrap-rethrow to tell the caller what it did wrong, rather than how it broke your code's logic. And if it's a signal to an unusual but foreseeable condition that you are able to handle, then you just handle it. In addition to that, you can do some "sanity checking" at the start of some methods and preventively throw a descriptive exception when you know some of the argument values will cause trouble, instead of waiting to the trouble actually arising (so this is an alternative to the catch-wrap-rethrow when the issue can be detected early).

Back on the client code (the code that uses your API), exceptions should be handled ASAP. Take that literally: as soon as possible, but not before it is actually possible. For example, a function that acts just as a wrapper to another one (a "home-made" curry) shouldn't try to handle exceptions triggered by the arguments it got passed, unless it can actually fix the issue and retry. Example (extremely generic):

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

In that scenario, handling exceptions from MyAPI.DoSomething can be a split work: if the exception is caused by the "some-predefined-string-argument" alone, then it's DoSomethingEasily's job to handle it. If the exception is caused by myObject, then DoSomethingEasily shouldn't mess up and let the outer code deal with their own trouble.

If there is some exception that is not caused by the arguments (for example, caused by some state of the API, or by external factors such as a device failing), the ASAP idea applies again: if DoSomethingEasily has enough information / context to be able to deal with these cases, then it definitely should. If it can't, however, it'll be better to not get in the way so the code calling it has a chance to deal with the problem.


Bonus suggestion: regardless of the case (reason), any exception thrown by your API should always be documented. If you are using C# with the Visual Studio IDE, then it's quite advisable to use the built-in XML comment documentation format, so the exceptions (and their description) will show up on Intellisense's tooltips.

Hope this helps.

巡山小妖精 2024-11-04 12:06:37

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

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

根据我的经验,捕获应该放置在距离 UI 最近的位置,这样您就可以以良好且最小的方式报告它。因此,类库中的“throw 语句”应该多于“catch 语句”。

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

Exceptin handling is a mechanism to prevent of returing (bad) results from one method to another and to isolate the exceptions from results.

For example you may call a method of your class library (named A) from UI, then A calls B and B calls C. Now there is a runtime problem in C method (Runtime exception). You could return something to B and say hey! there is an error here, then B should do the same for A and A for upper one too...
You see! you could just throw an exception in C then you dont need to catch it in B neither in A. Then you just put a try-catch block when calling A method in some upper layers and simply report the error without need to put any extra if statements. Of course there are some situations which you have to put your try-catch block in your class library (Ex. When you faced to an exception which is concerned only with your class library not the higher layers).

As my experience, the catchs should be placed in the nearest place to the UI where you can report it in a good and minimal way. So the "throw statements" should be more than "catch statements" in your class library.

Of course you can implement your own Exception classes for better error handling (see here).

北座城市 2024-11-04 12:06:37

而且 try/catch 应该“仅”在与外部服务通信时使用,此时您无法控制结果。否则,当您确实拥有控制权时,您应该避免引起异常,并在没有对象可用的情况下采用“返回 null”方法等。只是一个设计技巧;)

And also a try/catch should "only" be used when talking to external services, where you have no control over the results. Otherwise when you DO have control you should avoid causing exceptions and have a "return null" approach where no objects are available etc. Just a design tips ;)

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