OutOfRangeException与OutOfBoundsException

时间:2011-11-19 11:40:12

标签: php exception spl

PHP为无效密钥定义了两个SPL例外:

  

OutOfRangeException:请求非法索引时抛出异常。这表示应该在编译时检测到的错误。

     

OutOfBoundsException:如果值不是有效键,则抛出异常。这表示在编译时无法检测到的错误。

由于PHP不是编译语言,编译时和运行时之间的区别似乎很奇怪,因此我发现很难理解使用哪个例外。

目前我的理解是应该抛出...
...... OutOfRangeException如果密钥基本上和固有的格式错误,例如如果数组作为键传递。
... OutOfBoundsException如果密钥通常没问题,但不在某些边界,例如如果100已通过,但50是最大密钥。

这种理解是否正确?

5 个答案:

答案 0 :(得分:26)

虽然PHP没有经典的“编译时间”(或者编译器对此事进行了大量的静态检查),但我将“编译时间”视为“编写代码时我做错了”的相当静态的东西“和”运行时间“为”我的逻辑,输入或验证在某些时候关闭“。

所以我的建议就是像这样对待它:

"Compile Time" / "OutOfRangeException":错误始终可以在源代码中修复,不需要或只需很少的逻辑。

  

我总是从1-10开始,你输入11


"Run Time" / "OutOfBoundsException":错误是由于在运行时错误使用。

  

你创建了我并告诉我从1到5取值然后你输入7.不计算

  

你请求一个不在那里的索引,因为你没有把它放在那里


示例:

我希望SplFixedArray抛出一个OutOfBoundsException,因为它的大小是动态的,并且可以在运行时偶然发现像Calender::getMonthName这样的东西抛出OutOfRangeException因为月份数肯定固定在“编译/写入”时间。

数组对象样本:

假设$ array是一个实现ArrayAccess的对象,你可以在这些情况下抛出OutOfBoundsException

$array['bar'];
$array[7];

由于这些值是您对ArrayAccess所期望的值,但在SplFixedArray(5)的情况下它没有意义。替代方案可能是DomainExceptionRangeException

在这些情况下OutOfRangeException

$calendar->getMonth(15);

作为一个数组或一个新类,代码中肯定存在一些更大的逻辑缺陷,通常是程序员通过一个简单的“哦,我输入错误的变量”错误。一个(可能更可取的)替代方案是UnexpectedValueException和旧的InvalidArgumentException

对于以下情况:

$array[array()];
$array[new StdClass];

一些替代例外似乎更合适。

与Java世界进行比较,当Java开发人员无法始终使用该例外时,需要处理的附加问题。

已检查/未检查的例外情况。由于许多人认为所有不是运行时异常的东西在Java中使用非常有限/不应该在内部使用太多)这些名称已经失去了一些原始的含义和意图。

答案 1 :(得分:4)

你的问题的答案对我来说也是难以捉摸的。但是,有一些事情要考虑:

  • 如果在我们期望有效数组键时传入数组,我们也有InvalidArgumentException因为它不是正确的参数类型。
  • 我们也可以抛出DomainException,因为数组不在数组键的域中。
  • 在php中,由于后期静态绑定,通常无法在编译时检测类型。他们故意将变量绑定到运行时。

我如何处理这种情况:

  • 如果将变量传入任何参数不正确的函数,则抛出InvalidArgumentException。我在使用数组时仍然这样做。
  • 如果InvalidArgumentException传入null,则会丢弃OutOfBoundsException。这个可能很多东西因为没有输入null。为了简化错误代码检查,我只需坚持使用无效参数。
  • 当索引不在正确的范围内时,抛出BadFunctionCallException,就像您建议的那样。
  • 如果用户提供的函数作为参数的格式不正确,则抛出{{1}}。如果你的内部结构是一个数组,那么它们可以通过一个函数来修改它,所以偶尔会出现这种情况。

通常,我只能使用这三个例外来表示在特殊资源之外发生的所有错误(网络和数据库连接将是特殊资源)。第三个似乎更频繁地出现,但主要是我刚刚处理了前两个。

答案 2 :(得分:4)

这很简单:

OutOfRange 表示“您请求的密钥不在代码 中定义的 集合的索引中。”

OutOfBounds 表示“您请求的密钥不在已加载配置 定义的 集合的索引中。”

答案 3 :(得分:1)

这种情况的混乱来自几个因素。首先,PHP实际上被编译成字节码。有几种执行环境,这种编译形式在服务器上以相对永久的形式存在。但是,OutOfRangeException / OutOfBoundsException问题与此无关,它是关于记录这些特定异常类的人员所做的分类错误。

由于PHP是动态类型的,因此在编译时实际检查范围甚至类型通常是不可能的。手册指出应该在编译时引发OutOfRangeException,并且应该在运行时应用OutOfBoundsException,这是在此上下文中进行的错误区分。

两个手工条目都使用不清楚的非法索引意义的语言,但查看其父类的用法提供了一些线索:LogicExceptions由DomainException,InvalidArgumentException和LengthException等类扩展,而运行时异常是诸如UnexpectedValueException之类的东西,OverflowException和UnderflowException。从这种模式可以推断出OutOfRangeException可能应用于非法键类型,而OutOfBoundsException应该应用于类型正确但不在其容器范围内的索引值。

关于这些分类错误的PHP开发列表上有一些讨论,但问题比这更深入。实际上,两个异常实际上只能在运行时引发。您可以使用文档的变幻莫测来区分无效键类型和无效索引值之间的区别,但此时我们正在讨论PHP文档中的错误。

答案 4 :(得分:0)

  1. 如果您收到意外索引。即你希望 string ,但最终得到 integer ,反之亦然。然后你应该抛出 UnexpectedValueException 例外。
  2. 如果您获得了正确类型的索引但它不存在。然后提出 warning (trigger_error)并继续。预计这不会停止编程流程。
  3. 如果你有一个可迭代的对象或者应该在一个范围内迭代并达到它的极限(即文件的结尾),那么你应该抛出一个 OutOfBoundsException
  4. 其他任何内容都是 OutOfRangeException 的候选人。
  5. 外行人的说法。 OutOfBoundsException是正常的。这不是那么严重。这是经常发生的事情,应该得到照顾。迭代器可以使用它来保持读取数据,直到没有更多内容可读。这是一个逻辑错误。由某人使用代码而不是由编写代码的人制作。

    OutOfRangeException是严肃的事。有人应该查看源代码。有人应该知道发生了什么。这个很重要。从理论上讲,这绝不应该发生。调用911.这是一个编译时错误。由虚拟程序员制作。

    超出范围的异常由程序员编写,以防止其他程序员的错误。或者也许你自己将来。如果您觉得这样的事情永远不会发生,那么请使用超出范围。使用Out of Bounds可能发生的事情。