即使我已经在专业水平上编程了几年,但我仍然不完全理解错误处理。尽管我的应用程序运行良好,但错误处理并未在专业级别上实现,而是多种技术的结合与匹配。
我的错误处理没有任何结构。我想学习和理解它是如何在专业水平上实现的。这是我缺乏知识的领域。
什么时候应该使用异常,什么时候应该返回成功状态,以在逻辑流程中进行检查?可以混合异常并返回状态吗?
我主要使用C#编写代码。
即使我已经在专业水平上编程了几年,但我仍然不完全理解错误处理。尽管我的应用程序运行良好,但错误处理并未在专业级别上实现,而是多种技术的结合与匹配。
我的错误处理没有任何结构。我想学习和理解它是如何在专业水平上实现的。这是我缺乏知识的领域。
什么时候应该使用异常,什么时候应该返回成功状态,以在逻辑流程中进行检查?可以混合异常并返回状态吗?
我主要使用C#编写代码。
Answers:
对异常情况使用例外,您不能合理地期望经常遇到的异常,表明出现问题的异常。例如,如果网络中断,则对于Web服务器来说是一件例外的事情。如果数据库不可用,则表示出了点问题。如果缺少配置文件,则可能意味着用户将其弄乱了。
不要使用异常来处理错误的代码。为了检查代码的正确性,您应该使用断言,或者在.NET Framework 4和更高版本中使用代码协定(它取代断言并具有其他特别有价值的功能)。
在非例外情况下请勿使用例外。当用户被要求输入数字时,输入“狗”的事实并不是例外,因此不应例外。
选择例外类型时要小心。在需要时创建自己的类型。仔细选择继承,要记住,抓父母也将抓孩子。从不throw Exception
。
不要将返回代码用于错误。错误代码容易被掩盖,忽略,遗忘。如果有错误,请处理它或将其传播到上层堆栈。
如果期望某个方法返回错误并且该错误不是异常,请使用枚举,而不要使用错误编号。例:
// Note that the operation fails pretty often, since it deals with the servers which are
// frequently unavailable, and the ones which send garbage instead of the actual data.
private LoadOperationResult LoadProductsFromWeb()
{
...
}
的意思LoadOperationResult.ServerUnavailable
,LoadOperationResult.ParsingError
等更加明确的比,说,记住,代码12只意味着该服务器已关闭,并且代码13 -该数据不能被解析。
当错误代码引用通用代码时,请使用错误代码,该错误代码为在特定领域工作的每个开发人员都知道。例如,请勿为HTTP 404 Not Found或HTTP 500 Internal Server Error重新创建枚举值。
当心布尔值。迟早,您不仅要了解特定方法是成功还是失败,还需要知道原因。为此,异常和枚举要强大得多。
不要捕获所有异常(除非您处于堆栈的最顶端)。如果发现异常,则应该准备好处理它。捕获所有内容表明您不在乎代码是否正确运行。这可能会解决“我现在不想搜索如何解决此问题”,但迟早会伤害您。
在C#中,永远不要抛出这样的异常:
catch (SomeException ex)
{
...
throw ex;
}
因为您要破坏堆栈。而是这样做:
catch (SomeException)
{
...
throw;
}
编写异常消息时要付出努力。我看过几次类似throw Exception("wrong data")
或的东西throw Exception("shouldn't call this method in this context")
。其他开发人员,包括六个月后的您自己,都不知道什么数据是错误的,以及为什么或为什么我们不应该在上下文中调用某些方法,也不知道究竟是哪种上下文。
不要向用户显示异常消息。它们不是普通人所期望的,甚至对于开发人员自己来说也是不可读的。
不要本地化异常消息。在文档中搜索本地化的消息非常耗时且毫无意义:每条消息均应使用英文和英文。
不要只关注异常和错误:日志也非常重要。
在.NET中,请不要忘记在该方法的XML文档中包括异常:
/// <exception cref="MyException">Description of the exception</exception>
在XML文档中包含异常对于使用该库的人来说使事情变得容易得多。除了尝试猜测某个方法可能会抛出哪个异常以及原因之外,没有什么比这更令人烦恼了。
从这个意义上讲,Java异常处理提供了一种更严格,更好的方法。它迫使您要么处理被调用方法可能引发的异常,要么在您自己的方法中声明它可以引发您不处理的异常,从而使事情特别透明。
¹话虽这么说,但我发现Java对异常和错误的区分毫无用处和混乱,因为该语言已检查和未检查了异常。幸运的是,.NET Framework只有例外,没有错误。
我认为MainMa的清单非常完整。我将添加一些自己的:
public void Foo() {
try {
//get input from use
//do calculations
//open file
}
catch (Exception ex) {
//handle exception
}
}
而是这样做:
public void Foo() {
//get input from use
//do calculations
try {
//open file
}
catch (FileOpenException ex) {
//handle exception
}
}
不要将异常用于控制流。例如,不要在查找对话框中抛出ClientNotFoundException(在这种情况下,未找到客户端是非例外的),并且期望调用代码在发生这种情况时显示“未找到结果”消息。
不要吞下例外!
请记住,真正处理异常仅意味着三件事:
如果这些选项都不适用,那么您可能不应该捕获该异常。但是,您应该记录它,然后取消操作或关闭。当然,这取决于您对正确性与鲁棒性的要求。