据我所知,"例外是特殊情况下" [1],但除了只是被重复过和过一遍,我从来没有发现这一事实的实际原因.
作为他们停止执行,这是有道理的,你会不会希望他们为平原的条件逻辑,但为什么不输入验证?
假设你通过一组输入是循环和捕捉每个异常将它们组合在一起的用户通知...我不断地看到,这是某种"错误的",因为用户输入不正确输入所有的时间,但是这点似乎是基于在语义上.
输入不是预期的,因此是例外.抛出一个异常,让我解释清楚到底发生了什么事像StringValueTooLong或或IntegerValueTooLow或InvalidDateValue或什么的.为什么这被认为是错的?
替代抛出一个异常,将回移(最终收集)错误代码或差远了错误的字符串.然后我会直接显示这些错误字符串,或者解析错误代码然后向用户显示相应的错误消息.不会将异常视为可延展的错误代码吗?为什么要创建的错误代码和消息一个单独的表,当这些可以与例外的功能被推广已经内置到我的语言?
另外,我发现Martin Fowler的这篇文章是关于如何处理这些事情 - 通知模式.我不确定我是如何将此视为除了不停止执行的异常之外的任何东西.
a:我到处都读过有关例外的内容.
---编辑---
已经提出了许多重点.我对大多数事情都有评论,而且还有优点,但我还不完全相信.
我并不是要提倡将Exceptions作为解决输入验证的正确方法,但我想找到很好的理由,为什么这种做法被认为是如此邪恶,因为似乎大多数替代解决方案只是伪装的例外.
阅读这些答案,我发现说"异常只能用于特殊条件"是非常无益的.这引出了什么是"特殊情况"的整个问题.这是一个主观术语,其最佳定义是"您的正常逻辑流程不处理的任何条件".换句话说,异常条件是您使用异常处理的任何条件.
作为一个定义我很好,我不知道我们会比这更接近.但是你应该知道那是你正在使用的定义.
如果你要在某种情况下反对例外,你必须解释如何将条件的范围划分为"例外"和"非例外".
在某些方面,它类似于回答问题,"程序之间的界限在哪里?" 答案是,"无论你把开始和结束放在哪里",然后我们都可以谈论经验法则和不同的风格,以确定放置它们的位置.没有严格的规则.
输入"错误"输入的用户也不例外:这是预期的.
不应将例外用于正常控制流程.
在过去,许多作者都说过,例外本身就很昂贵.Jon Skeet的博客与此相反(并在SO上提到了一些答案),并表示它们并不像报道的那么昂贵(尽管我不提倡在紧密循环中使用它们!)
使用它们的最大原因是"意图陈述",即如果您看到异常处理块,您会立即看到在正常流程之外处理的异常情况.
除了已提到的原因之外还有一个重要的原因:
如果仅在例外情况下使用异常,则可以使用调试器设置在"抛出异常时停止"在调试器中运行.这非常方便,因为您在导致问题的确切行上插入调试器.使用此功能每天可为您节省大量时间.
在C#中这是可能的(我全心全意地推荐它),特别是在他们将TryParse方法添加到所有数字类之后.通常,没有一个标准库需要或使用"坏"异常处理.当我接近尚未写入此标准的C#代码库时,我总是最终将其转换为无异常的常规情况,因为stop-om-throw非常有价值.
在firebug javascript调试器中,您也可以执行此操作,前提是您的库不会严重使用异常.
当我编写Java时,这实际上是不可能的,因为很多东西都使用异常来处理非特殊情况,包括很多标准的java库.因此,这种节省时间的功能实际上无法在java中使用.我相信这是由于检查了异常,但我不会开始咆哮它们是如何邪恶的.
例外旨在报告错误,从而使代码更加健壮.要了解何时使用异常,必须首先了解错误是什么,什么不是错误.
功能是一个工作单元,故障应视为错误或基于其对功能的影响.在一个函数˚F,失败是错误的,当且仅当它可以防止˚F不能满足其任何被叫者的先决条件,实现任何的˚F自己的后置条件,或者重新建立任何不变的是˚F维持股份责任.
有三种错误:
阻止函数满足必须调用的另一函数的前提条件(例如,参数限制)的条件;
阻止函数建立自己的后置条件之一的条件(例如,产生有效的返回值是后置条件); 和
阻止函数重新建立它负责维护的不变量的条件.这是一种特殊的后置条件,特别适用于成员函数.每个非私有成员函数的基本后置条件是它必须重新建立其类的不变量.
任何其他条件都不是错误,不应报告为错误.
我想这是因为对"输入"的理解有点含糊不清,意思是函数的输入或字段的值,后者不应该抛出异常,除非它是失败函数的一部分.
可维护性 -异常会创建奇数代码路径,与GOTO不同。
易于使用(用于其他类)-其他类可以相信,从用户输入类引发的异常是实际错误
性能 -在大多数语言中,异常会导致性能和内存使用方面的损失。
语义 -单词的含义很重要。输入错误不是“例外”。
我认为差异取决于特定类别的合同,即
对于旨在处理用户输入的代码,以及针对它的防御程序(即清理它),为无效输入抛出异常是错误的 - 这是预期的.
对于旨在处理可能源自用户的已经过清理和验证的输入的代码,如果您发现某些意图被禁止的输入,则抛出异常将是有效的.在这种情况下,调用代码违反了合同,它表示清理和/或调用代码中的错误.