【问题标题】:InvalidArgumentException vs UnexpectedValueExceptionInvalidArgumentException 与 UnexpectedValueException
【发布时间】:2012-09-11 02:38:30
【问题描述】:

什么时候应该使用InvalidArgumentException,什么时候应该使用UnexpectedValueException?它们在我看来是一样的。

Note 一个扩展了 LogicException,另一个扩展了 RuntimeException,所以 IMO 的区别不应该那么细微。

【问题讨论】:

    标签: php exception spl


    【解决方案1】:

    仔细查看手册页上的描述:

    InvalidArgumentException

    如果参数不是预期的类型,则抛出异常

    (描述为Exception thrown if an argument does not match with the expected value.until mid-2014,但已更改when PHP 5.6 got introduced

    UnexpectedValueException

    如果一个值与一组值不匹配,则抛出异常。通常,当一个函数调用另一个函数并期望返回值是某种类型或 value[,] 不包括算术或缓冲区相关错误时,就会发生这种情况。

    由此,我们可以得出结论,InvalidArgumentException 旨在检查传递给函数的参数类型,而 UnexpectedValueException 旨在验证值与有效值集 em>,可能在函数的内部计算期间(例如从其他函数返回的值)。

    请注意,检查参数的值是一种灰色区域;可以说,由于 InvalidArgumentException extends LogicException,它应该只处理 should lead directly to a fix in your code. 的情况,因为在超出范围的输入值的情况下抛出异常可能是完全预期的 runtime 行为,这就留下了 UnexpectedValueException (扩展 RuntimeException)作为这种情况下的唯一候选者。

    【讨论】:

    【解决方案2】:

    我猜最大的区别是“论据”与“价值”。

    我认为InvalidArgumentException 适用于(通过)参数,而UnexpectedValueException 适用于(返回)。 “无效”和“意外”之间还有一个微妙但重要的区别 - 这也解释了为什么第一个是 LogicException 而第二个是 RuntimeException。

    例如:假设我有一个使用 Twitter-api 的函数,名为:getLastMessageDate($userid): 您传递一个(数字)用户 ID,它会将该用户的最后一条消息的日期作为 yyyy-mm-dd 字符串返回。

    现在,假设我使用字符串而不是数字作为参数调用此函数。此时我可以调用 InvalidArgumentException,因为提供的参数对于此函数无效。 这些检查可以由 logic 完成 - 因为变量要么是数字,要么不是。因此它是一个 LogicException。

    但是,函数的返回值 可能无法通过逻辑验证 - 尤其是在您处理(第三方)动态内容时。因为您永远无法确切知道您的函数将返回什么。 (如果你愿意,这可以说会使你的函数无用。)

    所以,这次我使用(有效)用户 ID 调用我的函数,我的函数获取该用户最后一条消息的日期。有了这个日期,我想做一些事情,比如格式化。

    现在想象一下 Twitter 的人做错了什么,而不是我的 预期 yyyy-mm-dd 日期字符串,我得到一个空字符串或另一个字符串说“blaaaa”。 此时,我可以抛出UnexpectedValueException

    我不能说这个值是“无效的”——我要求一个字符串,我得到了一个字符串。但它不是我所期待的“字符串类型”:因此 Unexpected ValueException.

    希望这可以解决问题。这是我的第一篇文章 - 到目前为止,我了解到写下我的想法并不是最简单的事情(英语也不是我的母语)。

    【讨论】:

    • italic “此时我可以调用 InvalidArgumentException,因为提供的参数对此函数无效” 您还可以将 UnexpectedValueException 抛出为你期待一个整数,但得到了一个意外的类型(字符串)。
    【解决方案3】:

    我的理解是,如果您根据可能值范围的固定列表检查参数,则应使用 InvalidArgumentException,即 LogicException。例如,检查用户输入的数据是否仅包含数字。 logic 程序可以处理这些值范围。

    UnexpectedValueException,作为RuntimeException只能在运行时发现/无法在编译时检测到的错误),将用于在可预见和指定输入之外发生的异常范围(可能作为上述“逻辑”检查后的最后手段)。

    回答这个问题的关键可能是UnexpectedValueException 中的Unexpected...Unexpected 表示程序逻辑中没有处理这个值。另一方面,Invalid 表明该值已被处理。

    【讨论】:

    • +1。我通常发现自己在defaultswitch 语句(例如,对于FSM 中的状态)的情况下使用UnexpectedValueExpection,它们应该处理一组有限的可能值。
    • @drrcknlsn,如果切换变量是从参数派生的,您还应该在switch 语句上方添加InvalidArgumentException 检查。
    • @drrcknlsn 我认为DomainException 会更适合。
    • +0 - 文档清楚地表明(并且更改使事情更加清晰)IAEx 是关于 type,而不是 value。这样,对可能值范围的固定列表进行检查是对这种异常 ATM 的滥用。
    猜你喜欢
    • 2015-09-24
    • 2016-06-11
    • 2017-12-18
    • 1970-01-01
    • 2023-04-04
    • 2019-01-05
    • 2018-05-08
    • 2016-02-28
    • 2016-05-17
    相关资源
    最近更新 更多