【发布时间】:2012-09-11 02:38:30
【问题描述】:
什么时候应该使用InvalidArgumentException,什么时候应该使用UnexpectedValueException?它们在我看来是一样的。
Note 一个扩展了 LogicException,另一个扩展了 RuntimeException,所以 IMO 的区别不应该那么细微。
【问题讨论】:
什么时候应该使用InvalidArgumentException,什么时候应该使用UnexpectedValueException?它们在我看来是一样的。
Note 一个扩展了 LogicException,另一个扩展了 RuntimeException,所以 IMO 的区别不应该那么细微。
【问题讨论】:
仔细查看手册页上的描述:
如果参数不是预期的类型,则抛出异常。
(描述为Exception thrown if an argument does not match with the expected value.until mid-2014,但已更改when PHP 5.6 got introduced)
如果一个值与一组值不匹配,则抛出异常。通常,当一个函数调用另一个函数并期望返回值是某种类型或 value[,] 不包括算术或缓冲区相关错误时,就会发生这种情况。
由此,我们可以得出结论,InvalidArgumentException 旨在检查传递给函数的参数类型,而 UnexpectedValueException 旨在验证值与有效值集 em>,可能在函数的内部计算期间(例如从其他函数返回的值)。
请注意,检查参数的值是一种灰色区域;可以说,由于 InvalidArgumentException extends LogicException,它应该只处理 should lead directly to a fix in your code. 的情况,因为在超出范围的输入值的情况下抛出异常可能是完全预期的 runtime 行为,这就留下了 UnexpectedValueException (扩展 RuntimeException)作为这种情况下的唯一候选者。
【讨论】:
我猜最大的区别是“论据”与“价值”。
我认为InvalidArgumentException 适用于(通过)参数,而UnexpectedValueException 适用于(返回)值。
“无效”和“意外”之间还有一个微妙但重要的区别 - 这也解释了为什么第一个是 LogicException 而第二个是 RuntimeException。
例如:假设我有一个使用 Twitter-api 的函数,名为:getLastMessageDate($userid):
您传递一个(数字)用户 ID,它会将该用户的最后一条消息的日期作为 yyyy-mm-dd 字符串返回。
现在,假设我使用字符串而不是数字作为参数调用此函数。此时我可以调用 InvalidArgumentException,因为提供的参数对于此函数无效。 这些检查可以由 logic 完成 - 因为变量要么是数字,要么不是。因此它是一个 LogicException。
但是,函数的返回值 可能无法通过逻辑验证 - 尤其是在您处理(第三方)动态内容时。因为您永远无法确切知道您的函数将返回什么。 (如果你愿意,这可以说会使你的函数无用。)
所以,这次我使用(有效)用户 ID 调用我的函数,我的函数获取该用户最后一条消息的日期。有了这个日期,我想做一些事情,比如格式化。
现在想象一下 Twitter 的人做错了什么,而不是我的 预期 yyyy-mm-dd 日期字符串,我得到一个空字符串或另一个字符串说“blaaaa”。
此时,我可以抛出UnexpectedValueException。
我不能说这个值是“无效的”——我要求一个字符串,我得到了一个字符串。但它不是我所期待的“字符串类型”:因此 Unexpected ValueException.
希望这可以解决问题。这是我的第一篇文章 - 到目前为止,我了解到写下我的想法并不是最简单的事情(英语也不是我的母语)。
【讨论】:
我的理解是,如果您根据可能值范围的固定列表检查参数,则应使用 InvalidArgumentException,即 LogicException。例如,检查用户输入的数据是否仅包含数字。 logic 程序可以处理这些值范围。
UnexpectedValueException,作为RuntimeException(只能在运行时发现/无法在编译时检测到的错误),将用于在可预见和指定输入之外发生的异常范围(可能作为上述“逻辑”检查后的最后手段)。
回答这个问题的关键可能是UnexpectedValueException 中的Unexpected...。 Unexpected 表示程序逻辑中没有处理这个值。另一方面,Invalid 表明该值已被处理。
【讨论】:
default 的switch 语句(例如,对于FSM 中的状态)的情况下使用UnexpectedValueExpection,它们应该处理一组有限的可能值。
switch 语句上方添加InvalidArgumentException 检查。
DomainException 会更适合。